﻿using System;
using System.Data;
using System.Drawing;
using System.Reflection;
using System.Windows.Forms;
using Lib.CommonForm;
using System.Web.Security;
using System.IO;
using Microsoft.Win32;
using System.Collections.Generic;
using WeifenLuo.WinFormsUI.Docking;
using Lib.Common;
using CustomUIControls;
using System.Text;
using System.Runtime.InteropServices;
using System.Diagnostics;

public delegate void DataInvoker(DataRow data);
public delegate void LookupInvoker(TextBoxHandle txtHandle, Globals.LookupMode eMode);
public delegate DataRow LookupInvokerEx(TextBoxHandle txtHandle, Globals.LookupMode eMode);
public delegate DataRow GridLookupInvoker(DataGridViewCell currentCell, string columnValue, Globals.LookupMode eMode);
public delegate void ListItemInvoker(ListViewItem itm);

public class FormGlobals : Globals
{
    #region "Detect idle time"
    private static MethodInvoker _IdleCallback;
    private static System.Timers.Timer _IdleTimer;
    private static TimeSpan _IdleTimeOut;

    internal static DateTime _IdleLastTime;
    public static void App_IdleHandle(MethodInvoker callbackMethod, TimeSpan idleTime)
    {
        _IdleCallback = callbackMethod;
        _IdleTimeOut = idleTime;
        if (_IdleTimer == null)
        {
            _IdleTimer = new System.Timers.Timer();
            _IdleTimer.Interval = 30000;
            _IdleTimer.Elapsed += _IdleTimer_Elapsed;
            Application.Idle += Application_OnIdle;
            Application.AddMessageFilter(new MyMessageFilter());
        }
        //
        _IdleTimer.Start();
    }

    public static TimeSpan App_IdleTime()
    {
        return (DateTime.Now - _IdleLastTime);
    }

    private static void Application_OnIdle(object sender, EventArgs e)
    {
        // keep track of the last time we went idle
        _IdleLastTime = DateTime.Now;
    }

    //Public Sub App_IdleStop()
    //    If Not _IdleTimer Is Nothing Then _IdleTimer.Stop()
    //End Sub

    private static void _IdleTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
    {
        if ((DateTime.Now - _IdleLastTime).TotalMilliseconds > _IdleTimeOut.TotalMilliseconds)
        {
            _IdleTimer.Stop();
            _IdleCallback.Invoke();
        }
    }
    #endregion

    #region "Private declare"
    private struct FormField
    {
        public string FieldName;
        public string ControlType;
        public string ControlName;
        public int DataLength;
        public byte DataScale;
        public string DataFormat;
        public string DataType;
        public bool Required;
        public object MaxValue;
        //
        public int PropertyIndex;
        public int DataColummIndex;
    }

    private struct FormProperty
    {
        public bool ControlBox;
        public FormBorderStyle FormBorderStyle;
        public bool ShowIcon;
        public bool ShowInTaskbar;
        public FormStartPosition StartPosition;
        public Point Location;
        public Size Size;
    }
    #endregion

    #region "Friend declare"
    internal static Keys Keys_Parse(string sText)
    {
        Keys key = Keys.None;
        if (string.IsNullOrEmpty(sText))
            return key;
        string[] arrKey = sText.Split('+');
        foreach (string sKey in arrKey)
        {
            switch (sKey)
            {
                case "Ctrl":
                    key = key | Keys.Control;
                    break;
                case "Alt":
                    key = key | Keys.Alt;
                    break;
                case "F1":
                    key = key | Keys.F1;
                    break;
                case "F2":
                    key = key | Keys.F2;
                    break;
                case "F3":
                    key = key | Keys.F3;
                    break;
                case "F4":
                    key = key | Keys.F4;
                    break;
                case "F5":
                    key = key | Keys.F5;
                    break;
                case "F6":
                    key = key | Keys.F6;
                    break;
                case "F7":
                    key = key | Keys.F7;
                    break;
                case "F8":
                    key = key | Keys.F8;
                    break;
                case "F9":
                    key = key | Keys.F9;
                    break;
                case "F10":
                    key = key | Keys.F10;
                    break;
                case "F11":
                    key = key | Keys.F11;
                    break;
                case "F12":
                    key = key | Keys.F12;
                    break;
                case "A": // TODO: to "Z"
                    key = key | (Keys)Asc(sKey);
                    break;
                default:
                    break; // TODO: might not be correct. Was : Exit For

            }
        }
        //
        return key;
    }
    public static short Asc(string String)
    {
        return Encoding.Default.GetBytes(String)[0];
    }
    public static string Chr(int CharCode)
    {
        if (CharCode > 255)
            throw new ArgumentOutOfRangeException("CharCode", CharCode, "CharCode must be between 0 and 255.");
        return Encoding.Default.GetString(new[] { (byte)CharCode });
    }
    #endregion

    //Control Style Defined
    public static string CS_FONT_NAME = "Tahoma";
    // Control view style
    public static string CS_STYLE_VIEW = "#e0e0e0";
    // Control required style
    public static string CS_STYLE_REQUIRED = "#FF4500;Bold";
    // Control info style
    public static string CS_STYLE_INFO = "#00008B;Bold";
    // Control note style
    public static string CS_STYLE_NOTE = "#00008B;Italic";
    // Control label style
    public static string CS_STYLE_LABEL = "#000000;Regular";
    // Control edit style
    public static string CS_STYLE_INPUT = "#000000;Bold";
    // Control toolbar edit style
    public static string CS_STYLE_TOOLBAR = "#000080;Bold;9";
    // Command button style
    public static string CS_STYLE_CMD = "#000000;Bold";
    // Control warning style
    public static string CS_STYLE_WARNING = "#CD2626;Bold";
    // Group Box style
    public static string CS_STYLE_GROUP = "#000000;Bold";
    //Grid alternative row background
    public static string CS_GRID_ROW_ALTER = "#efefef";
    //Grid normal row background
    public static string CS_GRID_ROW = "#ffffff";
    //Grid header cell style
    public static string CS_GRID_HEADER = "#CC0000;Bold";
    //Grid row cell style
    public static string CS_GRID_CELL = "#000000;Bold";
    //Message Defined
    public static string CS_DELETE_CONFIRM = "Are you sure you want to delete?";
    public static string CS_DATA_SAVING = "Saving data";
    public static string CS_DATA_SAVED = "Data saved";
    public static string CS_DATA_DELETING = "Deleting data";
    public static string CS_DATA_DELETED = "Data deleted";
    public static string CS_INPUT_NUMERIC = "Please input Numeric value";
    public static string CS_INPUT_INTEGER = "Please input Integer value";
    public static string CS_INPUT_DATE = "Please input Date value";
    public static string CS_INPUT_TIME = "Please input Time value";
    public static string CS_INPUT_EMAIL = "Please input Email address";
    public static string CS_INPUT_WEB = "Please input Web address";
    public static string CS_INPUT_REGEX = "Please input with pattern {0}";
    //Others Defined
    public static Keys CS_LOOKUP_KEY = Keys.F4;
    public static int CS_IDLE_TIMEOUT = 30;
    public static string CS_PAGER_LIST = "10;20;50;100";
    //Current user info
    public static long CS_USER_ID = 0;
    public static string CS_USER_NAME = "";
    public static string CS_USER_FULLNAME = "";
    //Danh sach theo Role Id
    public static string CS_USER_ROLES = "";
    //Danh sach theo Role Code
    public static string CS_USER_ROLES_CODE = "";
    public static long CS_UNIT_ID = 0;
    public static long CS_UNIT_ROOT = 0;
    public static string CS_USER_UNITS = "";

    //

    public static DataRowEx HotKeyData;

    public const string COMBO_ITEM_REQUIRE = "-- Please choose value --";
    public const string COMBO_ITEM_BLANK = "-- None --";
    public const string COMBO_ITEM_SELECT_ALL = "-- All --";
    public const string COMBO_ITEM_NULL_VALUE = "-1111111111";

    //Cau truc phuc vu cho viec SetFormField va Handle Input
    public struct FormControlExt
    {
        public bool Required;
        public string FieldName;
        public string DataFormat;
        public byte DataScale;
        public object HandleObject;
        public Control HandleControl;
        public object Tag;
        public object InitValue;
        public object PrevValue;
        public bool Lookup;
        //
        public EventHandler DefaultHandle;
        public Button DefaultButton;
    }

    public static string Client_Info()
    {
        string retVal = "";
        System.Net.NetworkInformation.NetworkInterface[] nics = System.Net.NetworkInformation.NetworkInterface.GetAllNetworkInterfaces();
        foreach (System.Net.NetworkInformation.NetworkInterface nic in nics)
        {
            if (retVal.Length > 0)
                retVal += ";";
            retVal += nic.GetPhysicalAddress().ToString();
        }
        return Environment.MachineName + "(" + retVal + ")";
    }

    public static string Environment_Info()
    {
        string retVal = null;
        retVal = string.Format("OS Version: {0}; OS User: {1}", Environment.OSVersion, Environment.UserName);
        return retVal;
    }

    public static string Function_Info()
    {
        string retVal = "";
        int iCount = Application.OpenForms.Count;
        if (iCount > 0)
        {
            Form activeForm = Application.OpenForms[iCount - 1];
            if (activeForm.IsMdiChild)
                activeForm = Application.OpenForms[0].ActiveMdiChild;
            retVal += string.Format("Form: {0} ({1})", activeForm.Name, activeForm.Text);
            if (activeForm.ActiveControl != null)
            {
                retVal += string.Format(";Control: {0} ({1})", activeForm.ActiveControl.Name, activeForm.ActiveControl.Text);
            }
        }
        return retVal;
    }

    public static void Form_InitDialog(Form f)
    {
        f.StartPosition = FormStartPosition.CenterScreen;
        //FormStartPosition.CenterParent
        f.ShowInTaskbar = false;
        f.FormBorderStyle = FormBorderStyle.FixedDialog;
        f.MinimizeBox = false;
        f.MaximizeBox = false;
        //Apply control style
        Control_SetStyle(f);
        //Handle enter key and focus to next control
        f.KeyPreview = true;
        f.KeyDown += Dialog_KeyDown;
        //'
    }

    public static void Form_InitEnter(Form f)
    {
        f.KeyPreview = true;
        f.KeyDown -= new KeyEventHandler(Dialog_KeyDown);
        f.KeyDown += new KeyEventHandler(Dialog_KeyDown);
    }

    public static void Dialog_KeyDown(object sender, KeyEventArgs e)
    {
        if (e.KeyCode == Keys.Enter)
        {
            Control controlObj = ((Form)sender).ActiveControl;
            string controlType = controlObj.GetType().Name;
            if ("TextBox,ComboBox".Contains(controlType))
            {
                if (controlType == "TextBox" && ((TextBox)controlObj).Multiline)
                    return;
                ((Form)sender).SelectNextControl(((Form)sender).ActiveControl, true, true, true, true);
            }
        }
    }

    public static void Form_BeginInit(ref Form objForm, bool KeepProperty)
    {
        var _with1 = objForm;
        if (KeepProperty)
        {
            FormProperty p = new FormProperty();
            p.ControlBox = _with1.ControlBox;
            p.FormBorderStyle = _with1.FormBorderStyle;
            p.Location = _with1.Location;
            p.ShowIcon = _with1.ShowIcon;
            p.ShowInTaskbar = _with1.ShowInTaskbar;
            p.Size = _with1.Size;
            p.StartPosition = _with1.StartPosition;
            _with1.Tag = p;
        }
        objForm.ControlBox = false;
        objForm.ShowIcon = false;
        objForm.ShowInTaskbar = false;
        objForm.StartPosition = FormStartPosition.Manual;
        objForm.WindowState = FormWindowState.Normal;
        objForm.Location = new Point(Screen.PrimaryScreen.WorkingArea.Width, Screen.PrimaryScreen.WorkingArea.Height);
        objForm.FormBorderStyle = FormBorderStyle.None;
        objForm.Show();
    }

    public static void Form_EndInit(Form objForm)
    {
        objForm.Hide();
        if (objForm.Tag is FormProperty)
        {
            FormProperty p = (FormProperty)objForm.Tag;
            var _with2 = objForm;
            _with2.ControlBox = p.ControlBox;
            _with2.FormBorderStyle = p.FormBorderStyle;
            _with2.ShowIcon = p.ShowIcon;
            _with2.ShowInTaskbar = p.ShowInTaskbar;
            _with2.Size = p.Size;
            if (p.StartPosition == FormStartPosition.Manual)
            {
                _with2.Location = p.Location;
            }
            else
            {
                _with2.Location = Point.Empty;
            }
            _with2.StartPosition = p.StartPosition;
        }
    }

    public static void Form_SetText(Form f, DataInputState mDataInputState)
    {
        Form_SetText(f, f.Text, mDataInputState, "");
    }

    public static void Form_SetText(Form f, string sFunctionName, DataInputState mDataInputState, string sDescText)
    {
        //Purpose: 
        //   Set caption text cho form show in tab
        //Parameters: 
        //   sFunctionName : tên chức năng
        //   mDataInputState: trạng thái nhập liệu (trường hợp form Browse sẽ = Nothing) 
        //   sDescText : ghi chú (thường là mã hoặc tên của đối tượng, nếu AddNew thì để trống)
        //Notes
        //               
        string sReturn = null;
        sReturn = sFunctionName.Trim() + " - ";

        switch (mDataInputState)
        {
            case DataInputState.BrowseMode:
                sReturn += "[Browse]";
                break;
            case DataInputState.AddMode:
                sReturn += "[New";
                break;
            case DataInputState.EditMode:
                sReturn += "[Edit";
                break;
            case DataInputState.ViewMode:
                sReturn += "[View";
                break;
            case DataInputState.CopyMode:
                sReturn += "[Copy";
                break;
            case DataInputState.VersionMode:
                sReturn += "[New Version";
                break;
            case DataInputState.ReviewMode:
                sReturn += "[Review";
                break;
            case DataInputState.ApproveMode:
                sReturn += "[Approve";
                break;
        }
        if (mDataInputState != DataInputState.BrowseMode)
        {
            if (sDescText.Length > 0)
            {
                sReturn += " - " + sDescText.Trim() + "]";
            }
            else
            {
                sReturn += "]";
            }
        }
        f.Text = sReturn;
    }

    public static void Control_ShowToolTip(Control ctl, string tip)
    {
        Control_ShowToolTip(ctl, tip, ToolTipIcon.Info, 1000);
    }

    public static void Control_ShowToolTip(Control ctl, string tip, ToolTipIcon icon, int duration)
    {
        ToolTip objToolTip = default(ToolTip);
        Control ctlDummy = ctl.FindForm().Controls[ctl.Name + "_ToolTip"];
        if (ctlDummy == null)
        {
            ctlDummy = new Control();
            ctlDummy.Name = ctl.Name + "_ToolTip";
            ctl.FindForm().Controls.Add(ctlDummy);
            objToolTip = new ToolTip();
            objToolTip.IsBalloon = true;
            objToolTip.UseAnimation = true;
            objToolTip.UseFading = true;
            objToolTip.AutoPopDelay = 3000;
            ctlDummy.Tag = objToolTip;
        }
        else
        {
            objToolTip = (ToolTip)ctlDummy.Tag;
        }
        objToolTip.ToolTipTitle = "";
        objToolTip.ToolTipIcon = icon;
        objToolTip.Show(tip, ctl, duration);
    }

    public static ToolTip Form_GetToolTip(Form f)
    {
        Control ctlDummy = f.Controls[f.Name + "_ToolTip"];
        ToolTip objToolTip = default(ToolTip);
        if (ctlDummy == null)
        {
            ctlDummy = new Control();
            ctlDummy.Name = f.Name + "_ToolTip";
            f.Controls.Add(ctlDummy);
            objToolTip = new ToolTip();
            objToolTip.ToolTipIcon = ToolTipIcon.Info;
            objToolTip.IsBalloon = true;
            objToolTip.UseAnimation = true;
            objToolTip.UseFading = true;
            objToolTip.AutoPopDelay = 3000;
            ctlDummy.Tag = objToolTip;
        }
        else
        {
            objToolTip = (ToolTip)ctlDummy.Tag;
        }
        return objToolTip;
    }

    public static ErrorProvider Form_GetErrorProvider(Form f)
    {
        if (f == null)
            return null;
        //
        Control ctlDummy = f.Controls[f.Name + "_ErrorProvider"];
        ErrorProvider objErrorProvider = default(ErrorProvider);
        if (ctlDummy == null)
        {
            ctlDummy = new Control();
            ctlDummy.Name = f.Name + "_ErrorProvider";
            f.Controls.Add(ctlDummy);
            objErrorProvider = new ErrorProvider();
            ctlDummy.Tag = objErrorProvider;
        }
        else
        {
            objErrorProvider = (ErrorProvider)ctlDummy.Tag;
        }
        return objErrorProvider;
    }



    public static FormBase Form_FindInTab(FormBase fChild)
    {
        return Form_FindInTab(fChild, fChild.Text);
    }

    public static FormBase Form_FindInTab(FormBase fChild, string fText)
    {
        //FormBase tabItem;
        FormBase f;

        foreach (var tabItem in dockPanel.Documents)
        {
            f = (FormBase)tabItem;
            if (f.FormId != fChild.FormId && f.Name + "|" + f.Text == fChild.Name + "|" + fText)
            {
                return f;
            }
        }
        return null;
    }
    public static bool Form_CheckOpened(string formName)
    {
        FormCollection fc = Application.OpenForms;

        foreach (Form frm in fc)
        {
            if (frm.Name == formName)
            {
                return true;
            }
        }
        return false;
    }

    public static bool Form_FindInTab(Form frmMain, string formNameOrText)
    {
        bool val = false;
        for (int i = 0; i < frmMain.MdiChildren.Length; i++)
        {
            if (frmMain.MdiChildren[i].Name == formNameOrText || frmMain.MdiChildren[i].Text == formNameOrText)
            {
                val = true;
                frmMain.MdiChildren[i].BringToFront();
                break;
            }
        }
        return val;
    }

    public static string Form_GetTabText(object sender)
    {
        return ((ToolStripMenuItem)sender).Text.Substring(4);
    }
    //-----------
    //<Control>
    //-----------

    //public void Control_SetValue(Control ctlSource, ref object objDest)
    //{
    //    //Purpose: 
    //    //   Sử dụng để lấy giá trị từ Control 
    //    //Parameters: 
    //    //   objSource : dữ liệu nguồn
    //    //   objDest   : dữ liệu đích
    //    //Notes:
    //    //   Thường dùng khi lấy giá trị trên Windows.Forms.Form nhập liệu để ghi vào CSDL
    //    //   Hỗ trợ nguồn là TextBox hoặc ComboBox
    //    object sValue = null;
    //    if (ctlSource is TextBox) {
    //        sValue = ctlSource.Text;
    //    } else if (ctlSource is ComboBox) {
    //        sValue = Combo_GetValue(ctlSource);
    //        //Chặn trường hợp là ITEM_NULL
    //        if (!Information.IsDBNull(sValue) && sValue == COMBO_ITEM_NULL_VALUE) {
    //            objDest = Null.SetNull(DBNull.Value, objDest);
    //            return;
    //        }
    //    } else {
    //        throw new Exception(string.Format("Control type '{0}' isn't support", ctlSource.GetType.Name));
    //    }
    //    Object_SetValue(sValue, objDest);
    //}

    public static void Control_SetFont(Control objControl, string fontName)
    {
        Control_SetFont(objControl, fontName, objControl.Font.Size);
    }

    public static void Control_SetFont(Control objControl, string fontName, float fontSize)
    {
        objControl.Font = new Font(fontName, fontSize, objControl.Font.Style);
    }

    public static void Control_SetStyle(Control objControl, string style)
    {
        Control_SetStyle(objControl, style, false);
    }

    public static void Control_SetStyle(Control objControl, string style, bool bOverwrite)
    {
        Font f = default(Font);
        string[] arrStyle = null;
        arrStyle = style.Split(';');
        //if (arrStyle.Length > 0 && (bOverwrite || objControl.ForeColor.IsSystemColor || objControl.ForeColor.ToString() == "Color [A=255, R=0, G=0, B=0]" || objControl.ForeColor == objControl.Parent.ForeColor))
        if (arrStyle.Length > 0 && (bOverwrite || objControl.ForeColor.IsSystemColor || objControl.ForeColor.ToString() == "Color [A=255, R=0, G=0, B=0]"))
            objControl.ForeColor = App_GetColor(arrStyle[0]);
        if (arrStyle.Length > 1)
        {
            float fontSize = objControl.Font.Size;
            if (arrStyle.Length == 3)
                fontSize = Globals.Object_GetValue<float>(arrStyle[2]);
            if (fontSize < 0)
                fontSize = objControl.Font.Size;
            switch (arrStyle[1])
            {
                case "Bold":
                    f = new Font(objControl.Font.FontFamily, fontSize, FontStyle.Bold);
                    break;
                case "Italic":
                    f = new Font(objControl.Font.FontFamily, fontSize, FontStyle.Italic);
                    break;
                default:
                    f = new Font(objControl.Font.FontFamily, fontSize, FontStyle.Regular);
                    break;
            }
            objControl.Font = f;
        }
    }

    public static Font Control_StyleFont(Font fontInit, string style)
    {
        Font f = default(Font);
        string[] arrStyle = null;
        arrStyle = style.Split(';');
        if (arrStyle.Length > 1)
        {
            switch (arrStyle[1])
            {
                case "Bold":
                    f = new Font(fontInit, FontStyle.Bold);
                    break;
                case "Italic":
                    f = new Font(fontInit, FontStyle.Italic);
                    break;
                default:
                    f = new Font(fontInit, FontStyle.Regular);
                    break;
            }
        }
        else
        {
            f = fontInit;
        }
        return f;
    }

    public static Color Control_StyleColor(Color colorInit, string style)
    {
        Color retVal = default(Color);
        string[] arrStyle = null;
        arrStyle = style.Split(';');
        if (arrStyle.Length > 0)
        {
            retVal = App_GetColor(arrStyle[0]);
        }
        else
        {
            retVal = colorInit;
        }
        return retVal;
    }

    public static void Control_SetStyle(DataGridViewCellStyle cellStyle, string style)
    {
        Font f = default(Font);
        string[] arrStyle = null;
        arrStyle = style.Split(';');
        if (arrStyle.Length > 0)
            cellStyle.ForeColor = App_GetColor(arrStyle[0]);
        if (arrStyle.Length > 1)
        {
            switch (arrStyle[1])
            {
                case "Bold":
                    f = new Font(cellStyle.Font, FontStyle.Bold);
                    break;
                case "Italic":
                    f = new Font(cellStyle.Font, FontStyle.Italic);
                    break;
                default:
                    f = new Font(cellStyle.Font, FontStyle.Regular);
                    break;
            }
            cellStyle.Font = f;
        }
    }

    public static void Control_SetStyle(Control objControl)
    {
        Control_SetStyle(objControl, CS_FONT_NAME, objControl.Font.Size);
    }

    public static void Control_SetStyle(Control objControl, string fontName, float fontSize)
    {
        if (Array.IndexOf<String>(cs_Control_Input, objControl.GetType().Name) >= 0)
        {
            Control_SetStyle(objControl, CS_STYLE_INPUT);
        }
        if (Array.IndexOf<String>(cs_Control_Toolbar, objControl.GetType().Name) >= 0)
        {
            Control_SetStyle(objControl, CS_STYLE_TOOLBAR);
        }
        else
        {
            if (!(objControl is ToolStrip) && objControl.Font != null && objControl.Font.Size > fontSize)
            {
                fontSize = objControl.Font.Size;
            }
            if (Globals.ToString(objControl.Tag).Trim().Length == 0)
                objControl.Font = new Font(fontName, fontSize, objControl.Font.Style);
        }
        if (objControl is DataGridView)
        {
            //Cell
            Control_SetStyle(((DataGridView)objControl).DefaultCellStyle, CS_GRID_CELL);
            //Header
            Control_SetStyle(((DataGridView)objControl).ColumnHeadersDefaultCellStyle, CS_GRID_HEADER);
            return;
        }
        else if (objControl is Label)
        {
            if (objControl.Tag == null)
            {
                Control_SetStyle(objControl, CS_STYLE_LABEL);
            }
            else
            {
                switch (objControl.Tag.ToString().ToUpper())
                {
                    case "INFO":
                        Control_SetStyle(objControl, CS_STYLE_INFO);
                        break;
                    case "NOTE":
                        Control_SetStyle(objControl, CS_STYLE_NOTE);
                        break;
                }
            }
            return;
        }
        else if (objControl is Button)//else if (objControl is Button && objControl.Name.StartsWith("cmd"))
        {
            Control_SetStyle(objControl, CS_STYLE_CMD);
            return;
        }
        else if (objControl is GroupBox && !string.IsNullOrEmpty(objControl.Text))
        {
            Control_SetStyle(objControl, CS_STYLE_GROUP);
        }
        else if (objControl is HeaderGroupBox && !string.IsNullOrEmpty(objControl.Text))
        {
            Control_SetStyle(objControl, CS_STYLE_GROUP);
        }
        else if (objControl is TableLayoutPanel)
        {
            Control_SetStyle(objControl, CS_STYLE_GROUP);
        }
        else if (objControl is TreeView)
        {
            Control_SetStyle(objControl, CS_STYLE_INPUT);
            return;
        }
        foreach (Control childControl in objControl.Controls)
        {
            Control_SetStyle(childControl, fontName, fontSize);
        }
    }

    public static void Control_SetFlat(Control objControl)
    {
        //If objControl.HasChildren And Not TypeOf objControl Is ToolStrip Then
        //    For Each objChild As Control In objControl.Controls
        //        Control_SetFlat(objChild)
        //    Next
        //    Return
        //End If
        //
        bool bDrawRect = false;
        //
        if (objControl is TextBox)
        {
            ((TextBox)objControl).BorderStyle = BorderStyle.FixedSingle;
        }
        else if (objControl is Button)
        {
            ((Button)objControl).FlatStyle = FlatStyle.Flat;
        }
        else if (objControl is CheckBox)
        {
            ((CheckBox)objControl).FlatStyle = FlatStyle.Flat;
        }
        else if (objControl is RadioButton)
        {
            ((RadioButton)objControl).FlatStyle = FlatStyle.Flat;
        }
        else if (objControl is ComboBox)
        {
            ((ComboBox)objControl).FlatStyle = FlatStyle.Flat;
            //
            bDrawRect = true;
        }
        else if (objControl is RichTextBox)
        {
            ((RichTextBox)objControl).BorderStyle = BorderStyle.None;
            bDrawRect = true;
        }
        else
        {
            if (!(objControl is ToolStrip))
            {
                foreach (Control objChild in objControl.Controls)
                {
                    Control_SetFlat(objChild);
                }
            }
            else
            {
                //For Each objItem As ToolStripItem In DirectCast(objControl, ToolStrip).Items
                //    If TypeOf objItem Is ToolStripTextBox Then
                //        DirectCast(objItem, ToolStripTextBox).BorderStyle = BorderStyle.FixedSingle
                //    End If
                //Next
            }
            return;
        }
        //
        if (!bDrawRect)
            return;
        //
        string ctlName = objControl.Name + "_Flat";
        Label ctlLabel = default(Label);
        if ((objControl.Visible || !objControl.FindForm().Visible) && !objControl.Parent.Controls.ContainsKey(ctlName))
        {
            objControl.Height -= 2;
            ctlLabel = new Label();
            ctlLabel.Name = objControl.Name + "_Flat";
            ctlLabel.AutoSize = false;
            ctlLabel.BorderStyle = BorderStyle.FixedSingle;
            ctlLabel.Width = objControl.Width;
            ctlLabel.Height = objControl.Height + 2;
            ctlLabel.Location = objControl.Location;
            objControl.Parent.Controls.Add(ctlLabel);
            ctlLabel.SendToBack();
            //
            objControl.Left += 1;
            objControl.Width -= 2;
            objControl.Top += 1;
            //
            objControl.VisibleChanged += new EventHandler(objControl_VisibleChanged);
            objControl.Resize += new EventHandler(objControl_Resize);
            objControl.Move += new EventHandler(objControl_Resize);
        }
        //'
    }

    public static void objControl_VisibleChanged(object sender, System.EventArgs e)
    {
        if (((Control)sender).Parent != null && ((Control)sender).Parent.Controls.ContainsKey(((Control)sender).Name + "_Flat"))
        {
            ((Control)sender).Parent.Controls[((Control)sender).Name + "_Flat"].Visible = ((Control)sender).Visible;
            if (((Control)sender).Visible)
                ((Control)sender).Parent.Controls[((Control)sender).Name + "_Flat"].SendToBack();
        }
    }

    public static void objControl_Resize(object sender, System.EventArgs e)
    {
        if (((Control)sender).Parent != null && ((Control)sender).Parent.Controls.ContainsKey(((Control)sender).Name + "_Flat"))
        {
            Label ctlLabel = (Label)((Control)sender).Parent.Controls[((Control)sender).Name + "_Flat"];
            ctlLabel.Width = ((Control)sender).Width + 2;
            ctlLabel.Height = ((Control)sender).Height + 2;
            ctlLabel.Top = ((Control)sender).Top - 1;
            ctlLabel.Left = ((Control)sender).Left - 1;
        }
    }

    public void Control_SetState(Control objControl, DataInputState sState)
    {
        //Purpose: 
        //   'Set trạng thái cho các ô nhập liệu theo trạng thái nhập liệu
        //Parameters: 
        //   objControl : đối tượng chứa nhóm Control (thường là Panel và GroupBox)
        //   sState: trạng thái nhập liệu
        //Notes
        //               
        foreach (Control mControl in objControl.Controls)
        {
            switch (mControl.GetType().Name)
            {
                case "TextBox":
                case "ComboBox":
                case "MultiColumnComboBox":
                case "DataGridView":
                    SetControlViewOnly(mControl, true, true, (sState == DataInputState.ViewMode), null);
                    break;
                case "ListBox":
                case "TreeView":
                    if (mControl.Parent.Parent is Form)
                    {
                        mControl.Enabled = (sState == DataInputState.ViewMode);
                    }
                    else
                    {
                        mControl.Enabled = !(sState == DataInputState.ViewMode);
                    }
                    break;
                case "Button":
                case "RadioButton":
                case "CheckBox":
                    mControl.Enabled = !(sState == DataInputState.ViewMode);
                    break;
                default:
                    if (mControl.HasChildren)
                    {
                        Control_SetState(mControl, sState);
                    }
                    break;
            }
        }
    }

    public void Control_SetViewOnly(Control objControl)
    {
        Control_SetViewOnly(objControl, true);
    }

    public void Control_SetViewOnly(bool viewOnly, params Control[] arrControl)
    {
        foreach (Control mControl in arrControl)
        {
            Control_SetViewOnly(mControl, viewOnly);
        }
    }

    public void Control_SetViewOnly(params Control[] arrControl)
    {
        foreach (Control mControl in arrControl)
        {
            Control_SetViewOnly(mControl, true);
        }
    }

    public void Control_SetViewOnly(Control objControl, string[] exceptControl)
    {
        Control_SetViewOnly(objControl, true, true, true, exceptControl);
    }

    public void Control_SetViewOnly(Control objControl, string[] exceptControl, bool bSetChildOnly)
    {
        Control_SetViewOnly(objControl, true, bSetChildOnly, true, exceptControl);
    }

    public void Control_SetViewOnly(Control objControl, bool bViewOnly)
    {
        Control_SetViewOnly(objControl, bViewOnly, true);
    }

    public void Control_SetViewOnly(Control objControl, bool bViewOnly, bool bSetChildOnly)
    {
        Control_SetViewOnly(objControl, bViewOnly, bSetChildOnly, true);
    }

    public void Control_SetViewOnly(Control objControl, bool bViewOnly, bool bSetChildOnly, bool bForceVisible)
    {
        Control_SetViewOnly(objControl, bViewOnly, bSetChildOnly, bForceVisible, null);
    }

    private void Control_SetViewOnly(Control objControl, bool bViewOnly, bool bSetChildOnly, bool bForceVisible, string[] exceptControl)
    {
        //Purpose: 
        //   Đặt trạng thái ViewOnly cho các ô nhập liệu
        //Parameters: 
        //   objControl : đối tượng Control hoặc đối tượng chứa nhóm Control cần set view only          
        //   bSetChildOnly : chỉ set cho các Child control, không đệ quy để tìm các Child of Child
        //   bForceVisible : không kiểm tra thuộc tính visible
        //Notes
        //                  

        if (objControl.HasChildren && !(objControl is DataGridView || objControl is System.Web.UI.WebControls.RadioButtonList))
        {
            System.Windows.Forms.Form objForm = null;
            if (!bForceVisible)
            {
                objForm = objControl.FindForm();
                if ((objForm != null))
                {
                    if (!objForm.Visible)
                    {
                        Form_BeginInit(ref objForm, true);
                    }
                    else
                    {
                        objForm = null;
                    }
                }
            }

            foreach (Control mControl in objControl.Controls)
            {
                SetControlViewOnly(mControl, bSetChildOnly, bForceVisible, bViewOnly, exceptControl);
            }

            if ((objForm != null))
            {
                Form_EndInit(objForm);
            }
        }
        else
        {
            SetControlViewOnly(objControl, bSetChildOnly, true, bViewOnly, null);
        }
    }

    //Thủ tục dùng để SetViewOnly đệ quy 
    private void SetControlViewOnly(Control objControl, bool bSetChildOnly, bool bForceVisible, bool bSetOn, string[] exceptControl)
    {
        if (bForceVisible == null) bForceVisible = false;
        if (bSetOn == null) bSetOn = true;

        if (!objControl.HasChildren || objControl is DataGridView || objControl is System.Web.UI.WebControls.RadioButtonList)
        {
            if (objControl.Visible | bForceVisible)
            {
                //Kiem tra danh sach loai tru

                if ((exceptControl != null) && Array.IndexOf<String>(exceptControl, objControl.Name) >= 0)
                    return;
                //Rẽ nhánh theo kiểu ô nhập liệu
                switch (objControl.GetType().Name)
                {
                    case "TextBox":
                        //Set ReadOnly, BackColor, BorderStyle
                        ((TextBox)objControl).ReadOnly = bSetOn;
                        ((TextBox)objControl).TabStop = !bSetOn;
                        if (bSetOn)
                        {
                            ((TextBox)objControl).BackColor = System.Drawing.ColorTranslator.FromHtml(CS_STYLE_VIEW);
                            //CType(objControl, TextBox).BorderStyle = BorderStyle.FixedSingle
                        }
                        else
                        {
                            ((TextBox)objControl).BackColor = SystemColors.Window;
                            //CType(objControl, TextBox).BorderStyle = BorderStyle.Fixed3D
                        }
                        break;
                    case "ComboBox":
                    case "MultiColumnComboBox":
                        //Khởi tạo 1 TextBox ReadOnly để hiển thị thay thế
                        TextBox objTextBox = default(TextBox);
                        objTextBox = (TextBox)objControl.Parent.Controls[objControl.Name + "_View"];
                        Control objFlat = default(Control);
                        objFlat = (Control)objControl.Parent.Controls[objControl.Name + "_Flat"];
                        if (bSetOn)
                        {
                            if (objTextBox == null)
                            {
                                objTextBox = new TextBox();
                                objTextBox.Location = objControl.Location;
                                objTextBox.Size = objControl.Size;
                                objTextBox.Anchor = objControl.Anchor;
                                objTextBox.Font = objControl.Font;
                                objTextBox.Name = objControl.Name + "_View";
                                objControl.Parent.Controls.Add(objTextBox);
                                Control_SetViewOnly(objTextBox, true);
                                if (((ComboBox)objControl).FlatStyle == FlatStyle.Flat)
                                {
                                    objTextBox.BorderStyle = BorderStyle.FixedSingle;
                                    objTextBox.Height = objControl.Height + 2;
                                }
                            }
                            objTextBox.Visible = true;
                            objTextBox.BringToFront();
                            objTextBox.Text = objControl.Text;
                        }
                        else
                        {
                            if ((objTextBox != null))
                                objTextBox.Visible = false;
                        }
                        if ((objFlat != null))
                            objFlat.Visible = !bSetOn;
                        objControl.Visible = !bSetOn;
                        break;
                    case "Button":
                    case "CheckedListBox":
                    case "RadioButton":
                    case "CheckBox":
                    case "TreeView":
                    case "RadioButtonList":
                        //Set Enabled cho các Control khác
                        if (!objControl.Name.EndsWith("_btnLookup"))
                        {
                            objControl.Enabled = !bSetOn;
                            objControl.TabStop = !bSetOn;
                        }
                        break;
                    case "DataGridView":
                        DataGridView objGrid = (DataGridView)objControl;
                        objGrid.ReadOnly = bSetOn;
                        objGrid.AllowUserToAddRows = !bSetOn;
                        objGrid.AllowUserToDeleteRows = !bSetOn;
                        if (bSetOn)
                        {
                            objGrid.RowHeadersWidth = 30;
                            objGrid.RowHeadersVisible = false;
                            objGrid.MultiSelect = false;
                            objGrid.SelectionMode = DataGridViewSelectionMode.FullRowSelect;
                        }
                        else
                        {
                            objGrid.RowHeadersWidth = 45;
                            objGrid.RowHeadersVisible = true;
                            objGrid.SelectionMode = DataGridViewSelectionMode.CellSelect;
                            objGrid.MultiSelect = true;
                        }
                        foreach (DataGridViewColumn mCol in objGrid.Columns)
                        {
                            if (mCol is DataGridViewButtonColumn && string.IsNullOrEmpty(mCol.DataPropertyName))
                            {
                                mCol.Visible = !bSetOn;
                            }
                        }

                        break;
                    case "RichTextBox":
                        RichTextBox objRichText = (RichTextBox)objControl;
                        objRichText.ReadOnly = bSetOn;
                        objControl.TabStop = !bSetOn;
                        if (bSetOn)
                        {
                            objRichText.BackColor = System.Drawing.ColorTranslator.FromHtml(CS_STYLE_VIEW);
                        }
                        else
                        {
                            objRichText.BackColor = SystemColors.Window;
                        }
                        break;
                    default:
                        //Các trường hợp khác
                        //Bỏ qua
                        return;
                }
                //Invisible/visible require
                Control ctl = objControl.Parent.Controls[objControl.Name + "_Required"];
                if ((ctl != null))
                    ctl.Visible = !bSetOn;
                //Set TabStop
                objControl.TabStop = !bSetOn;
            }
        }
        else
        {
            if ((objControl.Visible | bForceVisible) & bSetChildOnly == false)
            {
                foreach (Control mControl in objControl.Controls)
                {
                    SetControlViewOnly(mControl, bSetChildOnly, bForceVisible, bSetOn, exceptControl);
                }
            }
        }
    }

    public void Button_SetViewOnly(Control objControl)
    {
        Button_SetViewOnly(objControl, true);
    }

    //Đặt trạng thái ViewOnly cho các nút command
    public void Button_SetViewOnly(Control objControl, bool bViewOnly)
    {
        foreach (Control mControl in objControl.Controls)
        {
            if (!(mControl.Name == "cmdExit" || mControl.Name == "btnExit" || mControl.Name.IndexOf("cmdView") > -1 || mControl.Name.IndexOf("btnView") > -1))
            {
                mControl.Visible = !bViewOnly;
                //Else
                //    mControl.Visible = bViewOnly
            }
        }
    }

    public void Button_PopupClick(Button btn, ContextMenuStrip cms)
    {
        Button_PopupClick(btn, cms, null);
    }

    public void Button_PopupClick(Button btn, ContextMenuStrip cms, ToolStripItemClickedEventHandler evtHandler)
    {
        btn.Click += Button_Popup_Click;
        btn.Tag = cms;
        if ((evtHandler != null))
        {
            cms.ItemClicked += evtHandler;
        }
    }

    private void Button_Popup_Click(object sender, EventArgs e)
    {
        Button btn = (Button)sender;
        System.Drawing.Point mPoint = new System.Drawing.Point(btn.Width, 0);
        ((ContextMenuStrip)btn.Tag).Show(btn, mPoint);
    }


    //Đặt image tự động cho các nút toolbar
    public static void Toolbar_SetImage(ToolStrip toolbar)
    {
        SortedList<int, Button> lstButton = new SortedList<int, Button>();
        foreach (ToolStripItem mControl in toolbar.Items)
        {
            if (mControl is ToolStripButton)
            {
                Toolbar_SetImage((ToolStripButton)mControl);
            }
        }
    }

    public static void Toolbar_SetImage(ToolStripButton button)
    {
        string sName = button.Name.Substring(3);
        if (sName.Contains("_"))
            sName = sName.Substring(0, sName.IndexOf("_"));

        //Tìm tên ảnh tương ứng theo chiều cao của button
        int height = button.Height;
        if (height < 32)
            sName = sName + "16";
        else if (height > 32 && height < 48)
            sName = sName + "24";
        else if (height > 48)
            sName = sName + "48";

        object objRes = GetResouceImage(sName);
        if (objRes is Bitmap)
        {
            button.Image = (Bitmap)objRes;
            button.ImageScaling = ToolStripItemImageScaling.SizeToFit;
            if (height > 32)
            {
                button.DisplayStyle = ToolStripItemDisplayStyle.ImageAndText;
                button.TextImageRelation = TextImageRelation.ImageAboveText;
                button.ImageAlign = ContentAlignment.TopCenter;
                button.TextAlign = ContentAlignment.BottomCenter;
            }
            else
            {
                if (button.DisplayStyle == ToolStripItemDisplayStyle.ImageAndText)
                {
                    button.TextImageRelation = TextImageRelation.ImageBeforeText;
                    button.ImageAlign = ContentAlignment.MiddleLeft;
                    button.TextAlign = ContentAlignment.MiddleRight;
                }
            }
        }
        else
        {
            return;
        }

    }

    //Đặt image tự động cho các nút command
    public static void Panel_InitCommand(Control pnlCommand)
    {
        pnlCommand.BackgroundImage = Lib.CommonForm.Properties.Resources.bottom_gradient;
        pnlCommand.BackgroundImageLayout = ImageLayout.Tile;

        SortedList<int, Button> lstButton = new SortedList<int, Button>();
        foreach (Control mControl in pnlCommand.Controls)
        {
            if (mControl is Button)
            {
                int vLeft = mControl.Left;
                while (lstButton.ContainsKey(vLeft))
                {
                    vLeft += 1;
                }
                lstButton.Add(vLeft, (Button)mControl);
                //
                Button_SetImage((Button)mControl);
            }
        }
        //Auto tab index by position
        int tabIndex = 0;
        foreach (Button mButton in lstButton.Values)
        {
            mButton.TabIndex = tabIndex;
            tabIndex += 1;
        }
    }

    internal static Bitmap GetResouceImage(string sName)
    {
        if (string.IsNullOrEmpty(sName))
            return null;

        //Bỏ tiền tố btn trong tên ảnh đi

        //if (!sName.StartsWith("btn"))
        //    sName = "btn" + sName;

        //
        Bitmap objRes = default(Bitmap);
        if (ui_ImageResource.ContainsKey(sName.ToUpper()))
        {
            objRes = ui_ImageResource[sName.ToUpper()];
        }
        else
        {
            objRes = (Bitmap)Lib.CommonForm.Properties.Resources.ResourceManager.GetObject(sName);
            if (objRes == null)
            {
                //sName = "btn" + sName.Substring(3, 1).ToUpper() + sName.Substring(4).ToLower();
                objRes = (Bitmap)Lib.CommonForm.Properties.Resources.ResourceManager.GetObject(sName);
            }
        }
        return objRes;
    }

    public static void Button_SetImage(Control objControl)
    {
        if (objControl is Button)
        {
            string sName = objControl.Name.Substring(3);
            //Support image define in button Tag
            if ((objControl.Tag != null))
            {
                sName = objControl.Tag.ToString();
                if (sName.StartsWith("btn"))
                    sName = sName.Substring(3);
            }
            if (sName.Contains("_"))
                sName = sName.Substring(0, sName.IndexOf("_"));
            Button_SetImage((Button)objControl, sName);
        }

        else
        {
            foreach (Control mControl in objControl.Controls)
            {
                Button_SetImage(mControl);
            }
        }
    }

    public static void Button_SetImage(Button objButton, string imageKey)
    {
        //Tìm tên ảnh tương ứng theo chiều cao của button
        int height = objButton.Height;
        if (height < 32)
            imageKey = imageKey + "16";
        else if (height > 32 && height < 48)
            imageKey = imageKey + "32";
        else if (height > 48)
            imageKey = imageKey + "48";

        object objRes = GetResouceImage(imageKey);

        if (objRes is Bitmap)
        {
            if (objButton.Width < 70)
            {
                objButton.Width = 25;
                objButton.Text = "";
            }
            objButton.Image = (Bitmap)objRes;
            if (height > 32)
            {
                objButton.ImageAlign = ContentAlignment.TopCenter;
                objButton.TextAlign = ContentAlignment.BottomCenter;
            }
            else
            {
                objButton.ImageAlign = ContentAlignment.MiddleLeft;
                objButton.TextAlign = ContentAlignment.MiddleRight;
            }
        }
        else
        {
            return;
        }
    }

    public static void Button_SetState(Control objControl, DataInputState sState)
    {
        //Purpose: 
        //   'Set trạng thái cho các button theo trạng thái nhập liệu
        //Parameters: 
        //   objControl : đối tượng chứa nhóm Button Control (thường là Panel và GroupBox)
        //   sState: trạng thái nhập liệu
        //Notes
        //     
        string[] arrEditButton = new string[] { "Add", "Edit", "Update", "Delete", "Copy" };
        string[] arrSaveButton = new string[] { "Save", "OK", "Cancel" };
        foreach (Control mControl in objControl.Controls)
        {
            if (Array.IndexOf<String>(arrEditButton, mControl.Name.Substring(3)) >= 0)
            {
                mControl.Enabled = (sState == DataInputState.ViewMode);
            }
            else if (Array.IndexOf<String>(arrSaveButton, mControl.Name.Substring(3)) >= 0)
            {
                mControl.Enabled = !(sState == DataInputState.ViewMode);
            }
        }
    }

    public static void Button_SetWarning(Control objControl)
    {
        Button_SetWarning(objControl, true);
    }

    public static void Button_SetWarning(Control objControl, bool bWarning)
    {
        if (bWarning)
        {
            Control_SetStyle(objControl, CS_STYLE_WARNING, true);
        }
        else
        {
            Control_SetStyle(objControl, CS_STYLE_CMD, true);
        }
    }

    public static void Button_SetWarning(bool bWarning, params Control[] arrControl)
    {
        foreach (Control objControl in arrControl)
        {
            Button_SetWarning(objControl, bWarning);
        }
    }

    public static bool Control_GetRequired(Control mControl)
    {
        FormControlExt objFormControl = default(FormControlExt);
        if (mControl.Tag == null)
        {
            return false;
        }
        else
        {
            if (mControl.Tag is FormControlExt)
            {
                objFormControl = (FormControlExt)mControl.Tag;
                return objFormControl.Required;
            }
            else
            {
                return false;
            }
        }
    }

    public static void Control_SetRequired(params Control[] arrControl)
    {
        foreach (Control mControl in arrControl)
        {
            Control_SetRequired(mControl, true);
        }
    }

    public static void Control_SetRequired(Control mControl)
    {
        Control_SetRequired(mControl, true);
    }

    public static void Control_SetRequired(Control mControl, bool bSetOnOff)
    {
        //Purpose: 
        //   Thủ tục set hoặc unset bắt buộc nhập cho 1 ô nhập liệu TextBox hoặc ComboBox
        //Parameters: 
        //   mControl : đối tượng TextBox hoặc ComboBox
        //   bSetOn   : set required On/Off        
        //Notes:
        //   Auto make require sign and on/off required field

        FormControlExt objFormControl = default(FormControlExt);
        if (mControl.Tag == null)
        {
            objFormControl = new FormControlExt();
        }
        else
        {
            if (mControl.Tag is FormControlExt)
            {
                objFormControl = (FormControlExt)mControl.Tag;
            }
            else
            {
                if (!bSetOnOff)
                {
                    return;
                }
                else
                {
                    objFormControl = new FormControlExt();
                    objFormControl.Tag = mControl.Tag;
                }
            }
        }

        if (mControl.Parent != null)
        {
        }
        string sLabelName = mControl.Name + "_Required";
        Control objControl = default(Control);
        if (mControl.Parent != null)
        {
            if (!mControl.Parent.Controls.IsReadOnly)
            {
                objControl = mControl.Parent.Controls[sLabelName];
            }
            else
            {
                objControl = mControl.Parent.Parent.Controls[sLabelName];
            }
        }
        if (bSetOnOff)
        {
            Control mLabel = objControl;
            if (mLabel == null)
            {
                mLabel = new TransparentLabel();
                mLabel.Name = sLabelName;
                mLabel.Text = "*";
                mLabel.ForeColor = Color.Red;
                Control_SetStyle(mLabel, CS_STYLE_REQUIRED);
                if (mControl.Parent.Controls.IsReadOnly)
                {
                    mLabel.Top = mControl.Top + 3;
                    mLabel.Left = mControl.Left - 5;
                    mControl.Parent.Parent.Controls.Add(mLabel);
                }
                else
                {
                    mLabel.Top = mControl.Top;
                    mLabel.Left = mControl.Left - 8;
                    mControl.Parent.Controls.Add(mLabel);
                }
                mLabel.Visible = !(mControl is CheckBox);
                mLabel.BringToFront();
            }
            else
            {
                if (objControl.Name == sLabelName & objControl.Text == "*")
                {
                    objControl.Visible = true;
                }
            }
            objFormControl.Required = true;
        }
        else
        {
            if ((objControl != null))
            {
                if (objControl.Name == sLabelName & objControl.Text == "*")
                {
                    objControl.Visible = false;
                }
            }
            objFormControl.Required = false;
        }
        mControl.Tag = objFormControl;
    }

    public static string Control_GetLabelText(Control mControl)
    {
        //Purpose: 
        //   Hàm lấy control Label được set tab index liền ngay trước Control
        //Parameters: 
        //   mControl : đối tượng Control     
        //Notes:
        //   
        string sCaption = "";
        Control lblControl = Control_GetLabelControl(mControl);
        if ((lblControl != null))
        {
            sCaption = lblControl.Text.Replace("&", "");
            sCaption = sCaption.Replace("(*)", "");
            sCaption = sCaption.Replace(":", "");
            sCaption = sCaption.Trim();
        }
        //
        return sCaption;
    }

    public static Label Control_GetLabelControl(Control mControl)
    {
        //Purpose: 
        //   Hàm lấy control Label được set tab index liền ngay trước Control
        //Parameters: 
        //   mControl : đối tượng Control     
        //Notes:
        //   
        Control lblControl = mControl.Parent.GetNextControl(mControl, false);
        while ((lblControl != null))
        {
            if (lblControl is Label && lblControl.Text != "*")
            {
                break; // TODO: might not be correct. Was : Exit While
            }
            else
            {
                lblControl = lblControl.Parent.GetNextControl(lblControl, false);
            }
        }
        if ((lblControl != null) && Math.Abs(lblControl.Top - mControl.Top) > 15)
        {
            lblControl = null;
        }
        //
        return (Label)lblControl;
    }

    public static void Control_SetVisible(bool bVisible, params Control[] arrControl)
    {
        foreach (Control mControl in arrControl)
        {
            Control_SetVisible(mControl, bVisible);
        }
    }

    public static void Control_SetVisible(Control mControl, bool bVisible)
    {
        mControl.Visible = bVisible;
        Control lblControl = Control_GetLabelControl(mControl);
        if ((lblControl != null))
        {
            lblControl.Visible = bVisible;
        }
    }

    public static string App_GetTheme()
    {
        //Function to get the current Windows XP theme.
        //Optional: You can use it to set different colors for each theme.
        RegistryKey key = default(RegistryKey);
        string s = "WindowsClassic";
        key = Registry.CurrentUser.OpenSubKey("Software\\Microsoft\\Windows\\CurrentVersion\\ThemeManager");
        if (key != null)
        {
            if ("1" == (key.GetValue("ThemeActive").ToString()))
            {
                s = (key.GetValue("ColorName")).ToString();
            }
        }
        return s;
    }

    public static Color App_GetColor(string sColor)
    {
        if (sColor.StartsWith("#"))
        {
            return ColorTranslator.FromHtml(sColor);
        }
        else
        {
            return Color.FromName(sColor);
        }
    }

    public static long App_TextWidth(string sText, Font f)
    {
        return (long)App_TextSize(sText, f).Width;
    }

    public static SizeF App_TextSize(string sText, Font f)
    {
        Bitmap i = new Bitmap(1, 1);
        Graphics g = Graphics.FromImage(i);
        SizeF fSize = g.MeasureString(sText, f);
        return fSize;
    }

    public static DockPanel dockPanel;

    internal static Dictionary<string, Bitmap> ui_ImageResource = new Dictionary<string, Bitmap>();

    public static void App_InitResource(Type uiResource)
    {
        foreach (PropertyInfo propertyInfo in uiResource.GetProperties(System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic))
        {
            if (!(propertyInfo.PropertyType.Name == "Bitmap"))
                continue;
            if (ui_ImageResource.ContainsKey(propertyInfo.Name))
            {
                ui_ImageResource[propertyInfo.Name.ToUpper()] = (Bitmap)propertyInfo.GetValue(null, null);
            }
            else
            {
                ui_ImageResource.Add(propertyInfo.Name.ToUpper(), (Bitmap)propertyInfo.GetValue(null, null));
            }
        }
    }

    public static void App_Init()
    {
        /*
        //'Init global constant
        //DataRowEx drConstant = SystemController.Instance().SysParam_SelectGroup("CONSTANT");
        //
        Constant_SetValue(CS_DISPLAY_DATE_FORMAT, drConstant, "CS_DISPLAY_DATE_FORMAT");
        Constant_SetValue(CS_DISPLAY_TIME_FORMAT, drConstant, "CS_DISPLAY_TIME_FORMAT");
        Constant_SetValue(CS_DISPLAY_DATETIME_FORMAT, drConstant, "CS_DISPLAY_DATETIME_FORMAT");
        Constant_SetValue(CS_DISPLAY_TIMEDATE_FORMAT, drConstant, "CS_DISPLAY_TIMEDATE_FORMAT");
        Constant_SetValue(CS_DISPLAY_NUMBER_FORMAT, drConstant, "CS_DISPLAY_NUMBER_FORMAT");
        Constant_SetValue(CS_EDIT_DATE_FORMAT, drConstant, "CS_EDIT_DATE_FORMAT");
        Constant_SetValue(CS_EDIT_DATETIME_FORMAT, drConstant, "CS_EDIT_DATETIME_FORMAT");
        Constant_SetValue(CS_EDIT_TIME_FORMAT, drConstant, "CS_EDIT_TIME_FORMAT");
        Constant_SetValue(CS_DECIMAL_SYMBOL, drConstant, "CS_DECIMAL_SYMBOL");
        Constant_SetValue(CS_DECIMAL_SCALE, drConstant, "CS_DECIMAL_SCALE");
        Constant_SetValue(CS_DIGIT_GROUP_SYMBOL, drConstant, "CS_DIGIT_GROUP_SYMBOL");
        //Control style
        Constant_SetValue(CS_FONT_NAME, drConstant, "CS_FONT_NAME");
        Constant_SetValue(CS_STYLE_VIEW, drConstant, "CS_STYLE_VIEW");
        Constant_SetValue(CS_STYLE_INPUT, drConstant, "CS_STYLE_INPUT");
        Constant_SetValue(CS_STYLE_TOOLBAR, drConstant, "CS_STYLE_TOOLBAR");
        Constant_SetValue(CS_STYLE_LABEL, drConstant, "CS_STYLE_LABEL");
        Constant_SetValue(CS_STYLE_REQUIRED, drConstant, "CS_STYLE_REQUIRED");
        Constant_SetValue(CS_STYLE_INFO, drConstant, "CS_STYLE_INFO");
        Constant_SetValue(CS_STYLE_NOTE, drConstant, "CS_STYLE_NOTE");
        Constant_SetValue(CS_STYLE_CMD, drConstant, "CS_STYLE_CMD");
        Constant_SetValue(CS_STYLE_WARNING, drConstant, "CS_STYLE_WARNING");
        Constant_SetValue(CS_STYLE_GROUP, drConstant, "CS_STYLE_GROUP");
        //Grid style
        Constant_SetValue(CS_GRID_ROW_ALTER, drConstant, "CS_GRID_ROW_ALTER");
        Constant_SetValue(CS_GRID_ROW, drConstant, "CS_GRID_ROW");
        Constant_SetValue(CS_GRID_HEADER, drConstant, "CS_GRID_HEADER");
        Constant_SetValue(CS_GRID_CELL, drConstant, "CS_GRID_CELL");
        Constant_SetValue(DataGridHandle.CS_CHANGE_COLOR_NEW, drConstant, "CS_CHANGE_COLOR_NEW");
        Constant_SetValue(DataGridHandle.CS_CHANGE_COLOR_OLD, drConstant, "CS_CHANGE_COLOR_OLD");
        Constant_SetValue(DataGridHandle.CS_CHANGE_INTERVAL, drConstant, "CS_CHANGE_INTERVAL");
        Constant_SetValue(DataGridHandle.CS_CHANGE_NEWLIMIT, drConstant, "CS_CHANGE_NEWLIMIT");
        Constant_SetValue(DataGridHandle.CS_CHANGE_OLDLIMIT, drConstant, "CS_CHANGE_OLDLIMIT");
        //ComboBox
        Constant_SetValue(COMBO_ITEM_BLANK, drConstant, "COMBO_ITEM_BLANK");
        Constant_SetValue(COMBO_ITEM_REQUIRE, drConstant, "COMBO_ITEM_REQUIRE");
        Constant_SetValue(COMBO_ITEM_SELECT_ALL, drConstant, "COMBO_ITEM_SELECT_ALL");
        //Message
        Constant_SetValue(CS_DELETE_CONFIRM, drConstant, "CS_DELETE_CONFIRM");
        Constant_SetValue(CS_DATA_SAVING, drConstant, "CS_DATA_SAVING");
        Constant_SetValue(CS_DATA_SAVED, drConstant, "CS_DATA_SAVED");
        Constant_SetValue(CS_DATA_DELETING, drConstant, "CS_DATA_DELETING");
        Constant_SetValue(CS_DATA_DELETED, drConstant, "CS_DATA_DELETED");
        Constant_SetValue(CS_INPUT_DATE, drConstant, "CS_INPUT_DATE");
        Constant_SetValue(CS_INPUT_EMAIL, drConstant, "CS_INPUT_EMAIL");
        Constant_SetValue(CS_INPUT_INTEGER, drConstant, "CS_INPUT_INTEGER");
        Constant_SetValue(CS_INPUT_NUMERIC, drConstant, "CS_INPUT_NUMERIC");
        Constant_SetValue(CS_INPUT_REGEX, drConstant, "CS_INPUT_REGEX");
        Constant_SetValue(CS_INPUT_TIME, drConstant, "CS_INPUT_TIME");
        Constant_SetValue(CS_INPUT_WEB, drConstant, "CS_INPUT_WEB");
        //Remote config
        Constant_SetValue(DataAccess.CS_REMOTE_RECEIVE_MAXSIZE, drConstant, "CS_REMOTE_RECEIVE_MAXSIZE");
        Constant_SetValue(DataAccess.CS_REMOTE_RECEIVE_TIMEOUT, drConstant, "CS_REMOTE_RECEIVE_TIMEOUT");
        Constant_SetValue(DataAccess.CS_REMOTE_SEND_TIMEOUT, drConstant, "CS_REMOTE_SEND_TIMEOUT");
        //
        Constant_SetValue(CS_IDLE_TIMEOUT, drConstant, "CS_IDLE_TIMEOUT");
        Constant_SetValue(CS_PAGER_LIST, drConstant, "CS_PAGER_LIST");
        Keys lookupKey = Keys_Parse(drConstant("CS_LOOKUP_KEY"));
        if (lookupKey != Keys.None)
            CS_LOOKUP_KEY = lookupKey;
        //Get system hotkey define
        HotKeyData = SystemController.Instance().SysParam_SelectGroup("HOTKEY");

        */

        //Init main thread
        Application_SetCultureInfo(System.Threading.Thread.CurrentThread);
    }

    public static bool App_IsDebug()
    {
        return (Object_GetValue<bool>(Application_GetConfig("IsDebug")) || Debugger.IsAttached);
    }

    [DllImport("user32.dll")]
    public static extern bool SetForegroundWindow(IntPtr hWnd);


    private Dictionary<string, IntPtr> processHWND = new Dictionary<string, IntPtr>();

    public void Process_File(string fileName)
    {
        System.Diagnostics.Process proc = new System.Diagnostics.Process();
        proc.StartInfo.FileName = fileName;
        string ext = System.IO.Path.GetExtension(fileName).ToUpper();
        IntPtr hWnd = default(IntPtr);
        if (proc.Start())
        {
            hWnd = proc.MainWindowHandle;
            if (processHWND.ContainsKey(ext))
            {
                processHWND[ext] = hWnd;
            }
            else
            {
                processHWND.Add(ext, hWnd);
            }
            proc.WaitForInputIdle(1000);
        }
        else
        {
            if (processHWND.ContainsKey(ext))
            {
                hWnd = processHWND[ext];
            }
            else
            {
                Process[] prc = null;
                prc = Process.GetProcesses();
                string file = System.IO.Path.GetFileName(fileName);
                for (int i = 0; i <= prc.GetUpperBound(0); i++)
                {
                    if (prc[i].MainWindowTitle.Contains(file))
                    {
                        hWnd = prc[i].MainWindowHandle;
                        processHWND.Add(ext, hWnd);
                        break; // TODO: might not be correct. Was : Exit For
                    }
                }
            }
        }
        try
        {
            SetForegroundWindow(hWnd);
        }
        catch
        {
        }
    }

    public static string App_TempPath()
    {
        string sPath = System.IO.Path.GetTempPath() + "\\" + Application.ProductName;
        if (!System.IO.Directory.Exists(sPath))
            System.IO.Directory.CreateDirectory(sPath);
        return sPath;
    }

    public static string App_TempFile(string sExt)
    {
        if (string.IsNullOrEmpty(sExt))
            sExt = "tmp";
        if (!sExt.StartsWith("."))
            sExt = "." + sExt;
        string sFile = System.IO.Path.GetRandomFileName() + sExt;
        sFile = App_TempPath() + "\\" + sFile;
        return sFile;
    }

    public static void App_TempClear()
    {
        string sPath = App_TempPath();
        string[] filePaths = System.IO.Directory.GetFiles(sPath);
        try
        {
            foreach (string filePath in filePaths)
            {
                System.IO.File.Delete(filePath);
            }
        }
        catch
        {
        }
    }

    public static void ImageList_Init(ImageList imgList)
    {
        imgList.Images.Clear();
        //foreach (PropertyInfo propertyInfo in typeof(Lib.CommonForm.Properties.Resources).GetProperties(System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic).Where(info => object.ReferenceEquals(info.PropertyType, typeof(System.Drawing.Bitmap))))
        //{
        //    imgList.Images.Add(propertyInfo.Name, (System.Drawing.Bitmap)propertyInfo.GetValue(null, null));
        //}
    }

    public static void Menu_Init(ToolStripMenuItem mnuRoot, List<ToolStripItem> arrItem, ToolStripItemClickedEventHandler itemClick)
    {
        foreach (ToolStripItem item in arrItem)
        {
            if (item is ToolStripMenuItem)
            {
                ((ToolStripMenuItem)item).DropDownItemClicked += itemClick;
            }
        }
        mnuRoot.DropDownItems.Clear();
        mnuRoot.DropDownItems.AddRange(arrItem.ToArray());
        ((ToolStripMenuItem)mnuRoot).DropDownItemClicked += itemClick;
        FormGlobals.Menu_AutoShortcut(mnuRoot);
    }

    public static void Menu_AutoShortcut(ToolStripMenuItem mnuRoot)
    {
        int iIndex = 0;
        foreach (ToolStripItem itmChild in mnuRoot.DropDownItems)
        {
            if (itmChild is ToolStripMenuItem)
            {
                Menu_AutoShortcut((ToolStripMenuItem)itmChild);
                iIndex += 1;
                if ((!itmChild.Text.StartsWith("&")))
                {
                    itmChild.Text = string.Format("&{0}. ", iIndex.ToString("X")) + itmChild.Text;
                }
            }
        }
    }

    public static void Menu_AddItem(List<ToolStripItem> arrItem, string menuName, string menuText)
    {
        Menu_AddItem(arrItem, menuName, menuText, null);
    }

    public static void Menu_AddItem(List<ToolStripItem> arrItem, string menuName, string menuText, Type formType)
    {
        Menu_AddItem(arrItem, menuName, menuText, formType, null);
    }

    public static void Menu_AddItem(List<ToolStripItem> arrItem, string menuName, string menuText, Type formType, object initParam)
    {
        ToolStripMenuItem itemMenu = Menu_NewItem(menuName, menuText, formType, initParam);
        arrItem.Add(itemMenu);
    }

    public static void Menu_AddItem(List<ToolStripItem> arrItem)
    {
        arrItem.Add(new ToolStripSeparator());
    }

    public static ToolStripItem Menu_NewItem()
    {
        return new ToolStripSeparator();
    }

    public static ToolStripMenuItem Menu_NewItem(string menuName, string menuText)
    {
        ToolStripMenuItem itemMenu = new ToolStripMenuItem();
        itemMenu.Name = menuName;
        itemMenu.Text = menuText;
        return itemMenu;
    }

    public static ToolStripMenuItem Menu_NewItem(string menuName, string menuText, Type formType)
    {
        return Menu_NewItem(menuName, menuText, formType, null);
    }

    public static ToolStripMenuItem Menu_NewItem(string menuName, string menuText, Type formType, object initParam)
    {
        ToolStripMenuItem itemMenu = new ToolStripMenuItem();
        itemMenu.Name = menuName;
        itemMenu.Text = menuText;
        itemMenu.Tag = initParam;
        //
        if ((formType != null))
        {
            if (m_dicMenuForm.ContainsKey(menuName))
                m_dicMenuForm.Remove(menuName);
            m_dicMenuForm.Add(menuName, formType);
        }
        //
        return itemMenu;
    }

    public static Dictionary<string, Type> m_dicMenuForm = new Dictionary<string, Type>();

    public static FormBase Menu_GetForm(string menuName)
    {
        if (!m_dicMenuForm.ContainsKey(menuName))
            return null;
        FormBase objForm = (FormBase)Activator.CreateInstance(m_dicMenuForm[menuName]);
        //Return m_dicMenuForm(menuName)
        objForm.MenuName = menuName;
        return objForm;
    }

    public static bool Menu_ShowForm(ToolStripItem menuItem)
    {
        if (string.IsNullOrEmpty(menuItem.Name) || menuItem is ToolStripSeparator)
            return true;
        if (m_dicMenuForm.ContainsKey(menuItem.Name))
        {
            FormBase objForm = (FormBase)Activator.CreateInstance(m_dicMenuForm[menuItem.Name]);
            if ((objForm != null))
            {
                objForm.MenuName = menuItem.Name;
                objForm.InitValue = menuItem.Tag;
                objForm.Text = menuItem.Text.Substring(menuItem.Text.IndexOf(". ") + 2);
                objForm.Show_Form();
                return true;
            }
            else
            {
                return false;
            }
        }
        else if (m_dicMenuInvoke.ContainsKey(menuItem.Name))
        {
            m_dicMenuInvoke[menuItem.Name].Invoke();
            return true;
        }
        else
        {
            return false;
        }
    }

    public static ToolStripMenuItem Menu_NewItem(string menuName, string menuText, MethodInvoker invokeMethod)
    {
        ToolStripMenuItem itemMenu = new ToolStripMenuItem();
        itemMenu.Name = menuName;
        itemMenu.Text = menuText;
        //
        if ((invokeMethod != null))
        {
            if (m_dicMenuInvoke.ContainsKey(menuName))
                m_dicMenuForm.Remove(menuName);
            m_dicMenuInvoke.Add(menuName, invokeMethod);
        }
        //
        return itemMenu;
    }

    public static Dictionary<string, MethodInvoker> m_dicMenuInvoke = new Dictionary<string, MethodInvoker>();

    public static void Panel_FillData(Control ctlPanel, Standard_Info objInfo)
    {
        Panel_FillData(ctlPanel, objInfo, null);
    }

    public static void Panel_FillData(Control ctlPanel, Standard_Info objInfo, FormatInvoker customFormat)
    {
        Type objType = objInfo.GetType();
        foreach (Control mControl in ctlPanel.Controls)
        {
            string sControlType = mControl.GetType().Name;
            if (Array.IndexOf<String>(cs_Control_Input, sControlType) >= 0) //if (cs_Control_Input.Contains(sControlType))
            {
                PropertyInfo objProperty = Object_GetProperty(objType, mControl.Name.Substring(3));
                if (objProperty == null)
                    continue;
                object oValue = objProperty.GetValue(objInfo, null);
                if ((customFormat != null))
                    customFormat.Invoke(mControl.Name.Substring(3).ToUpper(), ref oValue);
                Control_SetValue(mControl, oValue);
            }
            else if (mControl.HasChildren)
            {
                Panel_FillData(mControl, objInfo);
            }
        }
    }

    public static void Panel_FillData(Standard_Info objInfo, params Control[] arrControl)
    {
        Type objType = objInfo.GetType();
        foreach (Control mControl in arrControl)
        {
            string sControlType = mControl.GetType().Name;
            if (Array.IndexOf<String>(cs_Control_Input, sControlType) >= 0) //if (cs_Control_Input.Contains(sControlType))
            {
                PropertyInfo objProperty = Object_GetProperty(objType, mControl.Name.Substring(3));
                if (objProperty == null)
                    continue;
                object oValue = objProperty.GetValue(objInfo, null);
                Control_SetValue(mControl, oValue);
            }
            else if (mControl.HasChildren)
            {
                Panel_FillData(mControl, objInfo);
            }
        }
    }

    public static void Panel_GetData(Standard_Info objInfo, params Control[] arrPanel)
    {
        foreach (Control ctlPanel in arrPanel)
        {
            Panel_GetData(ctlPanel, objInfo);
        }
    }

    public static void Panel_GetData(Control ctlPanel, Standard_Info objInfo)
    {
        Panel_GetData(ctlPanel, objInfo, null);
    }

    public static void Panel_GetData(Control ctlPanel, Standard_Info objInfo, FormatInvoker customFormat)
    {
        Type objType = objInfo.GetType();
        foreach (Control mControl in ctlPanel.Controls)
        {
            string sControlType = mControl.GetType().Name;
            if (Array.IndexOf<String>(cs_Control_Input, sControlType) >= 0) //if (cs_Control_Input.Contains(sControlType))
            {
                PropertyInfo objProperty = Object_GetProperty(objType, mControl.Name.Substring(3));
                if (objProperty == null)
                    continue;
                object objValue = Control_GetValue(mControl);
                if ((customFormat != null))
                    customFormat.Invoke(mControl.Name.Substring(3).ToUpper(), ref objValue);
                objValue = Object_SetValueEx(objValue, objProperty.PropertyType.Name, false);
                objProperty.SetValue(objInfo, objValue, null);
            }
            else if (Array.IndexOf<String>("Panel;GroupBox".Split(';'), sControlType) >= 0)  //if ("Panel;GroupBox".Split(';').Contains(sControlType))
            {
                Panel_GetData(mControl, objInfo);
            }
        }
    }

    public static void Panel_FillData(Control ctlPanel, DataRow objRow)
    {
        Panel_FillData(ctlPanel, objRow, null);
    }

    public static void Panel_FillData(Control ctlPanel, DataRow objRow, FormatInvoker customFormat)
    {
        foreach (Control mControl in ctlPanel.Controls)
        {
            string sControlType = mControl.GetType().Name;
            if (Array.IndexOf<String>(cs_Control_Input, sControlType) >= 0) //if (cs_Control_Input.Contains(sControlType))
            {
                if (!objRow.Table.Columns.Contains(mControl.Name.Substring(3)))
                    continue;
                object oValue = DB_GetValue(objRow[mControl.Name.Substring(3)], null);
                if ((customFormat != null))
                    customFormat.Invoke(mControl.Name.Substring(3).ToUpper(), ref oValue);
                Control_SetValue(mControl, oValue);
            }
            else if (mControl.HasChildren)
            {
                Panel_FillData(mControl, objRow);
            }
        }
    }

    public static void Control_FillData(Control.ControlCollection arrControl, DataRow objRowEx)
    {
        Control_FillData(arrControl, objRowEx, null);
    }

    public static void Control_FillData(Control.ControlCollection arrControl, DataRow objRowEx, FormatInvoker customFormat)
    {
        Array arr = Array.CreateInstance(typeof(Control), arrControl.Count);
        arrControl.CopyTo(arr, 0);
        Control_FillData(arrControl, objRowEx, customFormat);
    }

    public static void Control_FillData(Control[] arrControl, DataRow objRowEx)
    {
        Control_FillData(arrControl, objRowEx, null);
    }

    public static void Control_FillData(Control[] arrControl, DataRow objRowEx, FormatInvoker customFormat)
    {
        foreach (Control mControl in arrControl)
        {
            string sControlType = mControl.GetType().Name;
            if (Array.IndexOf<String>(cs_Control_Input, sControlType) >= 0)
            {
                if (objRowEx == null)
                {
                    Control_SetValue(mControl, null);
                    continue;
                }
                //if (!objRowEx.HasItem(mControl.Name.Substring(3)))
                //    continue;
                object oValue = objRowEx[mControl.Name.Substring(3)];
                if ((customFormat != null))
                    customFormat.Invoke(mControl.Name.Substring(3).ToUpper(), ref oValue);
                Control_SetValue(mControl, oValue);
            }
            else if (mControl.HasChildren)
            {
                Control_FillData(mControl.Controls, objRowEx, customFormat);
            }
        }
    }

    public static void Panel_GetData(Control ctlPanel, DataRow objRow)
    {
        Panel_GetData(ctlPanel, objRow, null);
    }

    public static void Panel_GetData(Control ctlPanel, DataRow objRow, FormatInvoker customFormat)
    {
        object objValue = null;
        foreach (Control mControl in ctlPanel.Controls)
        {
            string sControlType = mControl.GetType().Name;
            if (Array.IndexOf<String>(cs_Control_Input, sControlType) >= 0) //if (cs_Control_Input.Contains(sControlType))
            {
                if (!objRow.Table.Columns.Contains(mControl.Name.Substring(3)))
                    continue;
                objValue = Control_GetValue(mControl);
                objValue = Object_SetValueEx(objValue, objRow.Table.Columns[mControl.Name.Substring(3)].DataType.Name, true);
                if (objRow.Table.Columns[mControl.Name.Substring(3)].DataType.Name == "String")
                {
                    Int32 maxLen = objRow.Table.Columns[mControl.Name.Substring(3)].MaxLength;
                    if (maxLen > 0 && objValue.ToString().Length > maxLen)
                        objValue = objValue.ToString().Substring(0, maxLen);
                }
                if ((customFormat != null))
                    customFormat.Invoke(mControl.Name.Substring(3).ToUpper(), ref objValue);
                objRow[mControl.Name.Substring(3)] = objValue;
            }
        }
    }

    public static void Control_SetValueEx(object oValue, params Control[] arrControl)
    {
        foreach (Control mControl in arrControl)
        {
            Control_SetValue(mControl, oValue);
        }
    }

    public static void Control_SetValue(Control mControl, object oValue)
    {
        string sControlType = mControl.GetType().Name;
        object pValue = null;
        bool isLoading = ((FormBase)mControl.FindForm()).IsLoading;
        if (!isLoading)
            pValue = Control_GetValue(mControl);
        switch (sControlType)
        {
            case "TextBox":
            case "MaskedTextBox":
            case "ToolStripTextBoxControl":
                mControl.Text = DB_GetString(oValue);
                break;
            case "ComboBox":
            case "ToolStripComboBoxControl":
            case "MultiColumnComboBox":
                Combo_SetValue((ComboBox)mControl, oValue);
                break;
            case "RichTextBox":
                ((RichTextBox)mControl).Rtf = DB_GetString(oValue);
                break;
            case "CheckBox":
                ((CheckBox)mControl).Checked = DB_GetValue<bool>(oValue);
                break;
            case "CheckedListBox":
                if (oValue != null && oValue.GetType().IsArray)
                {
                    CheckedListBox_SetValue((CheckedListBox)mControl, oValue as object[]);
                }
                else
                {
                    CheckedListBox_SetValue((CheckedListBox)mControl, DB_GetString(oValue));
                }
                break;

            default:
                throw new Exception("Control type '" + sControlType + "' is not support");
        }
        FormControlExt ext = Control_GetExtension(mControl);
        if (isLoading)
            ext.InitValue = oValue;
        ext.PrevValue = pValue;
        Control_SetExtension(mControl, ext);
    }

    public static FormControlExt Control_GetExtension(Control mControl)
    {
        if (mControl.Tag is FormControlExt)
        {
            return (FormControlExt)mControl.Tag;
        }
        else
        {
            return new FormControlExt();
        }
    }

    public static void Control_SetExtension(Control mControl, FormControlExt ext)
    {
        if (mControl.Tag == null)
            return;
        if (mControl.Tag is FormControlExt)
        {
            ext.Tag = mControl.Tag;
        }
        else
        {

            ext.Tag = mControl.Tag;
        }
        ext.HandleControl = mControl;
        mControl.Tag = ext;
    }

    public static bool Control_IsChanged(Control mControl)
    {
        object objInit = Control_GetExtension(mControl).InitValue;
        object objValue = Control_GetValue(mControl);
        if ((objInit != null))
        {
            if (Control_GetExtension(mControl).DataFormat == CS_DISPLAY_TIME_FORMAT && objInit is DateTime)
            {
                objInit = ((DateTime)objInit).ToString(CS_DISPLAY_TIME_FORMAT);
            }
            if (objInit.GetType().Name != "String")
            {
                objValue = Object_SetValueEx(objValue, objInit.GetType().Name, false);
            }
            else if (objValue != null && objValue.GetType().Name != "String")
            {
                objInit = Object_SetValueEx(objInit, objValue.GetType().Name, false);
            }
        }
        return objValue != objInit;
    }

    private static string[] cs_Control_Input = new string[] { "TextBox", "MaskedTextBox", "DateTimePicker", "ComboBox", "MultiColumnComboBox", "CheckBox", "RichTextBox", "RadioButtonList", "CheckedListBox" };
    private static string[] cs_Control_Toolbar = new string[] { "ToolStripTextBoxControl", "ToolStripComboBoxControl" };

    public static bool Control_IsEditable(Control mControl)
    {
        string sControlType = mControl.GetType().Name;
        switch (sControlType)
        {
            case "TextBox":
            case "ToolStripTextBoxControl":
                return !(((TextBox)mControl).ReadOnly || !((TextBox)mControl).Enabled);
            case "RichTextBox":
                return !(((RichTextBox)mControl).ReadOnly || !((RichTextBox)mControl).Enabled);
            default:
                return mControl.Enabled;
        }
    }

    public static object Control_GetValue(Control mControl)
    {
        string sControlType = mControl.GetType().Name;
        switch (sControlType)
        {

            case "TextBox":
            case "ToolStripTextBoxControl":
                return mControl.Text;
            case "ComboBox":
                return Combo_GetValue((ComboBox)mControl);
            case "MultiColumnComboBox":
                return Combo_GetValue((ComboBox)mControl);
            case "RichTextBox":
                return ((RichTextBox)mControl).Rtf;
            case "CheckBox":
                return ((CheckBox)mControl).Checked;
            case "CheckedListBox":
                return CheckedListBox_GetValue((CheckedListBox)mControl);
            default:
                return null;
        }
    }

    public static object Control_GetValue(Control mControl, string sDataType)
    {
        object oValue = Control_GetValue(mControl);
        return Object_SetValueEx(oValue, sDataType, false);
    }

    public static T Control_GetValue<T>(Control mControl, T nullValue)
    {
        T objReturn = Control_GetValue<T>(mControl);
        if (Null.IsNull(objReturn))
        {
            objReturn = nullValue;
        }
        return objReturn;
    }

    public static T Control_GetValue<T>(Control mControl)
    {
        object oValue = Control_GetValue(mControl);

        return DB_GetValue<T>(oValue);
    }

    public static bool Panel_CheckError(Control objControl)
    {
        return Panel_CheckError(objControl, false);
    }

    public static bool Panel_CheckError(Control objControl, bool bSilent)
    {
        //Purpose: 
        //   Tự động kiểm tra dữ liệu cần phải nhập trên form
        //Parameters: 
        //   objControl : đối tượng chứa các ô nhập liệu
        //   bSilent : check Silent True/False
        //Notes:
        //   Nếu ở chế độ check Silent sẽ không hiện MessageBox
        bool bInput = true;
        Control mControl = default(Control);
        string sControlType = null;
        SortedList<int, Control> arrControl = new SortedList<int, Control>();
        //Sort control by tab index
        if (objControl.Tag is FormControlExt)
        {
            arrControl.Add(objControl.TabIndex, objControl);
        }
        else
        {
            for (int i = 0; i <= objControl.Controls.Count - 1; i++)
            {
                mControl = objControl.Controls[i];
                sControlType = mControl.GetType().Name;
                if (mControl.Controls.Count > 0 & mControl.Enabled & (sControlType.IndexOf("Panel") > -1 | sControlType.IndexOf("Tab") > -1 | sControlType.IndexOf("Group") > -1))
                {
                    arrControl.Add(mControl.TabIndex, mControl);
                }
                else
                {
                    if (mControl.Tag is FormControlExt)
                    {
                        arrControl.Add(mControl.TabIndex, mControl);
                    }
                    else
                    {
                        continue;
                    }
                }
            }
        }
        //
        bool bReturn = true;
        foreach (var nControl in arrControl.Values)
        {
            if (!(mControl.Tag is FormControlExt))
            {
                bReturn = Panel_CheckError(nControl, bSilent);
            }
            else
            {
                bReturn = Control_CheckError(nControl, bSilent);
            }
            if (!bReturn)
                break; // TODO: might not be correct. Was : Exit For
        }
        //
        return bReturn;
    }

    public static bool Control_CheckError(Control mControl)
    {
        return Control_CheckError(mControl, false);
    }

    public static bool Control_CheckError(Control mControl, bool bSilent)
    {
        string sControlType = mControl.GetType().Name;
        FormControlExt objControlExt = (FormControlExt)mControl.Tag;
        //
        bool bRequired = true;
        //Check required
        switch (sControlType)
        {
            case "TextBox":
                if (objControlExt.Required)
                {
                    bRequired = (!string.IsNullOrEmpty(mControl.Text.Trim()));
                }
                break;
            case "ComboBox":
            case "MultiColumnComboBox":
                if (objControlExt.Required)
                {
                    bRequired = !Null.IsNull(Combo_GetValue((ComboBox)mControl));
                }
                break;
            case "RichTextBox":
                if (objControlExt.Required)
                {
                    bRequired = !string.IsNullOrEmpty(((RichTextBox)mControl).Rtf.Trim());
                }
                break;
            case "DataGridView":
                if (objControlExt.Required)
                {
                    bRequired = ((DataGridView)mControl).Rows.Count > 0 && ((DataGridView)mControl).Rows[0].IsNewRow == false;
                }
                break;
            //bReturn = bReturn AndAlso DirectCast(objControlExt.HandleObject, DataGridHandle).CheckValid(bSilent)
            case "RadioButtonList":
                //if (objControlExt.Required)
                //{
                //    bRequired = (((System.Web.UI.WebControls.RadioButtonList)mControl).SelectedIndex >= 0);
                //}
                bRequired = false;
                break;
            case "CheckedListBox":
                if (objControlExt.Required)
                {
                    bRequired = CheckedListBox_GetValue((CheckedListBox)mControl).Length > 0;
                }
                break;
            default:
                if (sControlType != "CheckBox" && objControlExt.Required)
                {
                    bRequired = (!string.IsNullOrEmpty(mControl.Text.Trim()));
                }
                break;
        }
        //
        string sError = null;
        bool bError = false;
        string sCaption = null;
        //Check validation error
        if (sControlType == "TextBox" && ((TextBox)mControl).ReadOnly == false)
        {
            sError = Control_GetError(mControl);
        }
        else if (sControlType == "DataGridView")
        {
            //sError = ((DataGridHandle)objControlExt.HandleObject).CheckError();
        }
        else
        {
            sError = Control_GetError(mControl);
        }
        bError = !string.IsNullOrEmpty(sError);
        if ((!bRequired) | bError)
        {
            if (!bSilent)
            {
                //Hỗ trợ trường hợp nằm trong tabpage không active
                Control ctlParent = mControl.Parent;
                while (!(ctlParent is Form))
                {
                    if (ctlParent is TabPage)
                    {
                        if (((TabControl)ctlParent.Parent).SelectedIndex != ((TabPage)ctlParent).TabIndex)
                        {
                            //DirectCast(ctlParent.Parent, TabControl).SelectedIndex = DirectCast(ctlParent, TabPage).TabIndex
                            ((TabControl)ctlParent.Parent).SelectedTab = (TabPage)ctlParent;
                            break; // TODO: might not be correct. Was : Exit While
                        }
                    }
                    ctlParent = ctlParent.Parent;
                }
                //
                mControl.Focus();
                //
                sCaption = Control_GetLabelText(mControl);
                if (sControlType == "DataGridView")
                {
                    if (!bError && !bRequired)
                    {
                        sError = "You must input at least one row grid data";
                        if (!string.IsNullOrEmpty(sCaption))
                            sError += " for '" + sCaption + "'";
                    }
                }
                else if (sControlType == "CheckedListBox")
                {
                    if (!bError && !bRequired)
                    {
                        sError = "You must checked at least one check value";
                        if (!string.IsNullOrEmpty(sCaption))
                            sError += " for '" + sCaption + "'";
                    }
                }
                else
                {
                    if (string.IsNullOrEmpty(sCaption))
                    {
                        sCaption = "required field";
                    }
                    else
                    {
                        sCaption = "'" + sCaption + "'";
                    }
                    if (!bError && !bRequired)
                    {
                        //sCaption = "You must input value for " + sCaption
                        sError = "You must input value for all required field (mark with * sign)";
                    }
                    if (bError)
                    {
                        if (sCaption != "required field")
                        {
                            sError = sError + " for " + sCaption;
                        }
                        bRequired = false;
                    }
                }
                Message_Warning(sError);
            }
            return false;
        }
        return true;
    }

    public static bool Panel_IsChanged(Control objControl)
    {
        if (!objControl.HasChildren)
        {
            throw new Exception("Panel_IsChanged not suppport control " + objControl.GetType().Name);
        }
        bool retVal = false;
        foreach (Control mControl in objControl.Controls)
        {
            if (Array.IndexOf<String>(cs_Control_Input, mControl.GetType().Name) >= 0)
            {
                retVal = Control_IsChanged(mControl);
            }
            else if (mControl.HasChildren)
            {
                retVal = Panel_IsChanged(mControl);
            }
            if (retVal)
                break; // TODO: might not be correct. Was : Exit For
        }
        return retVal;
    }

    public static void Control_ClearData(Control.ControlCollection arrControl)
    {
        Control[] arr = (Control[])Array.CreateInstance(typeof(Control), arrControl.Count);
        arrControl.CopyTo(arr, 0);
        Control_ClearData(arr);
    }

    public static void Control_ClearData(params Control[] arrControl)
    {
        foreach (Control mControl in arrControl)
        {
            switch (mControl.GetType().Name)
            {
                case "TextBox":
                    mControl.Text = "";
                    break;
                case "ComboBox":
                case "MultiColumnComboBox":
                    if (((ComboBox)mControl).Items.Count > 0)
                    {
                        ((ComboBox)mControl).SelectedIndex = 0;
                    }
                    break;
                case "ListBox":
                    if (!(mControl.Parent.Parent is Form))
                    {
                        ((ListBox)mControl).Items.Clear();
                    }
                    break;
                case "TreeView":
                    if (!(mControl.Parent.Parent is Form))
                    {
                        ((TreeView)mControl).Nodes.Clear();
                    }
                    break;
                case "ListView":
                    if (!(mControl.Parent.Parent is Form))
                    {
                        ((ListView)mControl).Items.Clear();
                    }
                    break;
                case "CheckBox":
                    ((CheckBox)mControl).Checked = false;
                    break;
                case "DataGridView":
                    ((DataGridView)mControl).DataSource = null;
                    break;
                case "Panel":
                case "GroupBox":
                case "TabPage":
                    if (mControl.HasChildren)
                    {
                        Control_ClearData(mControl.Controls);
                    }
                    break;
            }
        }
    }

    public static void Control_ClearHandle(params Control[] arrControl)
    {
        foreach (Control ctl in arrControl)
        {
            if (ctl.Tag is FormControlExt)
            {
                FormControlExt ext = (FormControlExt)ctl.Tag;
                ext.HandleObject = null;
                ctl.Tag = ext;
            }
        }
    }

    public static void Panel_ClearData(params Control[] arrControl)
    {
        foreach (Control objControl in arrControl)
        {
            Panel_ClearData(objControl);
        }
    }
    //Clear data khi nhập bản ghi mới
    public static void Panel_ClearData(Control objControl)
    {
        if (!objControl.HasChildren)
        {
            throw new Exception("Panel_ClearData not suppport control " + objControl.GetType().Name);
        }
        Control_ClearData(objControl.Controls);
    }

    public void Panel_GetControlValue(Control objPanel, Standard_Info objInfo)
    {
        string sTableName = objPanel.Tag.ToString();
        Panel_GetControlValue(objPanel, objInfo, sTableName);
    }

    public void Panel_GetControlValue(Control objPanel, Standard_Info objInfo, string sTableName)
    {
        List<FormField> arrFormField = FormField_GetCache(objPanel, sTableName);
        //
        if (arrFormField == null)
        {
            throw new Exception(string.Format("Control '{0}' isn't init control with table '{1}'", objPanel.Name, sTableName));
        }
        //
        PropertyInfo objProperty = default(PropertyInfo);
        object objValue = null;
        foreach (FormField mFormField in arrFormField)
        {
            Control mControl = (Control)Find_Control(objPanel, mFormField.ControlName);
            if (mControl == null)
                continue;
            objProperty = Object_GetProperty(objInfo.GetType(), mFormField.FieldName);
            if (objProperty == null || !objProperty.CanWrite)
                continue;
            objValue = objProperty.GetValue(objInfo, null);
            //Dim objFormControl As New FormControlExt
            if (mFormField.ControlType == "TextBox")
            {
                //objValue = DirectCast(mControl, TextBox).Text
                objValue = TextBox_GetValue((TextBox)mControl);
            }
            else if (mFormField.ControlType == "RichTextBox")
            {
                objValue = ((RichTextBox)mControl).Rtf;
            }
            else if (mFormField.ControlType == "ComboBox" || mFormField.ControlType == "MultiColumnComboBox")
            {
                objValue = Combo_GetValue((ComboBox)mControl);
            }
            else if (mFormField.ControlType == "CheckBox")
            {
                objValue = ((CheckBox)mControl).Checked;
            }
            else if (mFormField.ControlType == "RadioButtonList")
            {
                //objValue = Control_GetValue((RadioButtonList)mControl);
            }
            else
            {
                continue;
                //Throw New Exception("Not support type of control")
            }
            objValue = Object_SetValueEx(objValue, objProperty.PropertyType.Name, false);
            objProperty.SetValue(objInfo, objValue, null);
        }
    }

    public void Panel_SetControlValue(Control objPanel, Standard_Info objInfo)
    {
        Panel_SetControlValue(objPanel, objInfo, false);
    }

    public void Panel_SetControlValue(Control objPanel, Standard_Info objInfo, bool bIgnoreError)
    {
        string sTableName = objPanel.Tag.ToString();
        Panel_SetControlValue(objPanel, objInfo, sTableName, bIgnoreError);
    }

    public void Panel_SetControlValue(Control objPanel, Standard_Info objInfo, string sTableName)
    {
        Panel_SetControlValue(objPanel, objInfo, sTableName, false);
    }

    public void Panel_SetControlValue(Control objPanel, Standard_Info objInfo, string sTableName, bool bIgnoreError)
    {
        List<FormField> arrFormField = FormField_GetCache(objPanel, sTableName);
        //
        if (arrFormField == null)
        {
            throw new Exception(string.Format("Control '{0}' isn't init control with table '{1}'", objPanel.Name, sTableName));
        }
        //
        PropertyInfo objProperty = default(PropertyInfo);
        object objValue = null;
        foreach (FormField mFormField in arrFormField)
        {
            Control mControl = (Control)Find_Control(objPanel, mFormField.ControlName);
            if (mControl == null)
                continue;
            objProperty = Object_GetProperty(objInfo.GetType(), mFormField.FieldName);
            objValue = objProperty.GetValue(objInfo, null);
            //
            if (Array.IndexOf<String>(cs_Control_Input, mFormField.ControlType) >= 0)
            {
                Control_SetValue(mControl, objValue);
            }
            else
            {
                throw new Exception("Not support type of control: " + mControl.GetType().Name);
            }
        }
    }

    //-------------------------------------
    //Luu lai ket qua SetFormField de reuse
    //-------------------------------------
    static Dictionary<string, List<FormField>> mFieldCache = new Dictionary<string, List<FormField>>();

    static Dictionary<string, DataTable> mTableCache = new Dictionary<string, DataTable>();
    //
    //
    public static object Find_Control(Control mParentControl, string sName)
    {
        if (mParentControl.Controls.ContainsKey(sName))
        {
            return mParentControl.Controls[sName];
        }
        else
        {
            Control[] arrControl = mParentControl.Controls.Find(sName, true);
            if (arrControl.Length == 0)
                return null;
            return arrControl[0];
        }
    }
    //
    private static List<FormField> FormField_GetCache(Control objControl, string sTableName)
    {
        string sKey = ControlField_GetKey(objControl, sTableName);
        if (!(mFieldCache.ContainsKey(sKey)))
        {
            return null;
        }
        else
        {
            return mFieldCache[sKey];
        }
    }

    private void Panel_SetRequired(Control ctlPanel, string[] arrRequiredField)
    {
        foreach (Control ctlInput in ctlPanel.Controls)
        {
            if (Array.IndexOf<String>(cs_Control_Input, ctlInput.GetType().Name) >= 0)
            {
                if (Array.IndexOf<String>(arrRequiredField, ctlInput.Name.Substring(3).ToUpper()) >= 0)
                {
                    Control_SetRequired(ctlInput);
                }
            }
            else if (ctlInput.HasChildren)
            {
                Panel_SetRequired(ctlInput, arrRequiredField);
            }
        }
    }

    private void SetRequiredNote(System.Windows.Forms.Form objForm)
    {
        string sKey = "pnlRequired_Note";

        if (!objForm.Controls.ContainsKey(sKey))
        {
        }
    }

    internal object NumericMaxValue(ref string dataType, byte dataLen, byte dataScale)
    {
        object iMaxValue = null;
        if (dataScale > 0)
        {
            if (dataLen >= double.MaxValue.ToString().Length)
            {
                iMaxValue = double.MaxValue;
                dataType = "DOUBLE";
            }
            else if (dataLen >= decimal.MaxValue.ToString().Length)
            {
                iMaxValue = decimal.MaxValue;
                dataType = "DECIMAL";
            }
            else
            {
                iMaxValue = Math.Pow(10, (dataLen - dataScale)) - 1 / (Math.Pow(10, dataScale));
            }
        }
        else
        {
            if (dataLen > int.MaxValue.ToString().Length | dataLen == 0)
            {
                iMaxValue = long.MaxValue;
                dataType = "LONG";
            }
            else if (dataLen > short.MaxValue.ToString().Length)
            {
                iMaxValue = int.MaxValue;
                dataType = "INTEGER";
            }
            else
            {
                iMaxValue = Math.Pow(10, (dataLen)) - 1;
                dataType = "SMALLINT";
            }
        }
        return iMaxValue;
    }

    private static string ControlField_GetKey(Control objControl, string sTableName)
    {
        return objControl.FindForm().Name + "|" + objControl.Name + "|" + sTableName;
    }

    public static void Control_SetError(string sError, params Control[] arrControl)
    {
        foreach (Control objControl in arrControl)
        {
            Control_SetError(objControl, sError);
        }
    }

    public static void Control_SetError(Control objControl, string sError)
    {
        ErrorProvider errPro = Form_GetErrorProvider(objControl.FindForm());
        if (errPro == null)
            return;
        errPro.SetError(objControl, sError);
        if (!string.IsNullOrEmpty(sError))
        {
            Control objErrControl = objControl.Parent.GetChildAtPoint(new Point(objControl.Left - 18, objControl.Top));
            int iPadding = 2;
            if ((objErrControl != null) && objErrControl is TextBox)
            {
                if (((TextBox)objErrControl).ReadOnly)
                    iPadding += objControl.Left - objErrControl.Left;
            }
            errPro.SetIconAlignment(objControl, ErrorIconAlignment.TopLeft);
            errPro.SetIconPadding(objControl, iPadding);

            System.Windows.Forms.Form mForm = objControl.FindForm();
            if (mForm.AutoValidate != AutoValidate.EnableAllowFocusChange)
                mForm.AutoValidate = AutoValidate.EnableAllowFocusChange;
        }
    }

    public static string Control_GetError(Control objControl)
    {
        ErrorProvider errPro = default(ErrorProvider);
        errPro = Form_GetErrorProvider(objControl.FindForm());
        return errPro.GetError(objControl);
    }

    public static object Control_GetTag(Control objControl)
    {
        if (objControl.Tag is FormControlExt)
        {
            return ((FormControlExt)objControl.Tag).Tag;
        }
        else
        {
            return objControl.Tag;
        }
    }

    public static T Control_GetTag<T>(Control objControl)
    {
        T objReturn = default(T);
        object oValue = Control_GetTag(objControl);
        return Globals.Object_GetValue<T>(oValue);

    }

    public static void Control_SetTag(Control objControl, object objTag)
    {
        if (objControl.Tag is FormControlExt)
        {
            FormControlExt obj = (FormControlExt)objControl.Tag;
            obj.Tag = objTag;
            objControl.Tag = obj;
        }
        else
        {
            objControl.Tag = objTag;
        }
    }
    /*
    public static void Control_SetContext(Control objControl, Control pnlCommand)
    {
        Control_SetContext(objControl, pnlCommand, new string[] {
		"Update",
		"Edit",
		"Delete"
	});
    }

    public static void Control_SetContext(Control objControl, Control pnlCommand, string[] arrCommand)
    {
        Control_SetContext(objControl, pnlCommand, arrCommand, new string[] {
		"Close",
		"Exit"
	});
    }
    
    public static void Control_SetContext(Control objControl, Control pnlCommand, string[] arrCommand, string[] arrExcept)
    {
        //Dim ctxCommand As ContextMenuStrip
        //ctxCommand = New ContextMenuStrip()
        //ctxCommand.Name = "ctxCommand_" + objControl.Name
        //'
        //AddHandler ctxCommand.ItemClicked, AddressOf Context_ItemClick
        //ctxCommand.Tag = pnlCommand
        //
        SortedList<int, Button> lstCommand = new SortedList<int, Button>();
        //Sort by Tab Index
        //
        foreach (Control btnCommand in pnlCommand.Controls)
        {
            if (btnCommand is Button)
            {
                string commandName = btnCommand.Name;
                if ((arrExcept != null) && (Array.IndexOf<String>(arrExcept, commandName) >= 0))
                    continue;
                commandName = commandName.Substring(3);
                if (commandName.Contains("_"))
                    commandName = commandName.Substring(0, commandName.IndexOf("_") - 1);
                if ((arrExcept != null) && (Array.IndexOf<String>(arrExcept, commandName) >= 0))
                    continue;
                if (arrCommand == null || (Array.IndexOf<String>(arrExcept, commandName) >= 0))
                {
                    lstCommand.Add(((Button)btnCommand).TabIndex, (Button)btnCommand);
                }
            }
        }
        //
        //For Each btnCommand As Button In lstCommand.Values
        //    Dim ctxMenu As New ToolStripMenuItem
        //    ctxMenu.Name = "ctxCommand_" + btnCommand.Name
        //    ctxMenu.Text = btnCommand.Text
        //    ctxMenu.Image = DirectCast(btnCommand, Button).Image
        //    ctxMenu.Tag = btnCommand.Name
        //    '
        //    ctxCommand.Items.Add(ctxMenu)
        //Next
        //'
        //If TypeOf objControl Is DataGridView Then
        //    DirectCast(objControl, DataGridView).ContextMenuStrip = ctxCommand
        //ElseIf TypeOf objControl Is ListView Then
        //    DirectCast(objControl, ListView).ContextMenuStrip = ctxCommand
        //End If
        Control_SetContext((objControl, lstCommand);
    }

    public static void Control_SetContext(Control objControl, params Button[] arrButton)
    {
        ContextMenuStrip ctxCommand = default(ContextMenuStrip);
        ctxCommand = new ContextMenuStrip();
        ctxCommand.Name = "ctxCommand_" + objControl.Name;
        //
        ctxCommand.ItemClicked += Context_ItemClick;
        //
        foreach (Button btnCommand in arrButton)
        {
            if (btnCommand == null)
            {
                ctxCommand.Items.Add(new ToolStripSeparator());
            }
            else
            {
                ToolStripMenuItem ctxMenu = new ToolStripMenuItem();
                ctxMenu.Name = "ctxCommand_" + btnCommand.Name;
                ctxMenu.Text = btnCommand.Text;
                ctxMenu.Image = ((Button)btnCommand).Image;
                ctxMenu.Tag = btnCommand;
                //
                ctxCommand.Items.Add(ctxMenu);
            }
        }
        //
        if (objControl is DataGridView)
        {
            ((DataGridView)objControl).ContextMenuStrip = ctxCommand;
        }
        else if (objControl is ListView)
        {
            ((ListView)objControl).ContextMenuStrip = ctxCommand;
        }
    }
    
    public static void Context_ItemClick(object sender, ToolStripItemClickedEventArgs e)
    {
        Button btnCommand = default(Button);
        if (e.ClickedItem.Tag is Button)
        {
            btnCommand =(Button) e.ClickedItem.Tag;
        }
        else
        {
            Control pnlCommand = ((Control)sender).Tag;
            btnCommand = pnlCommand.Controls(e.ClickedItem.Tag.ToString());
        }
        btnCommand.PerformClick();
    }
    */
    public static void Control_SetDefault(Control objControl, Button defaultButton)
    {
        if (objControl is TextBox || objControl is ComboBox)
        {
            if (!(objControl.Tag is FormControlExt))
            {
                objControl.Tag = new FormControlExt();
            }
            FormControlExt mField = (FormControlExt)objControl.Tag;
            mField.DefaultButton = defaultButton;
            objControl.Tag = mField;
            objControl.KeyPress += Event_Key_Press;
        }
        else
        {
            switch (objControl.GetType().Name)
            {
                case "ToolStrip":
                    foreach (ToolStripItem item in ((ToolStrip)objControl).Items)
                    {
                        if (item is ToolStripTextBox)
                        {
                            Control_SetDefault(((ToolStripTextBox)item).TextBox, defaultButton);
                        }
                        else if (item is ToolStripComboBox)
                        {
                            Control_SetDefault(((ToolStripComboBox)item).ComboBox, defaultButton);
                        }
                    }

                    break;
                default:
                    foreach (Control item in objControl.Controls)
                    {
                        if (item is TextBox)
                        {
                            Control_SetDefault((TextBox)item, defaultButton);
                        }
                    }

                    break;
            }
        }
    }

    public static void Control_SetDefault(Control objControl, EventHandler defaultHandle)
    {
        if (objControl is TextBox || objControl is ComboBox)
        {
            if (!(objControl.Tag is FormControlExt))
            {
                objControl.Tag = new FormControlExt();
            }
            FormControlExt mField = (FormControlExt)objControl.Tag;
            mField.DefaultHandle = defaultHandle;
            objControl.Tag = mField;
            objControl.KeyPress += Event_Key_Press;
        }
        else
        {
            switch (objControl.GetType().Name)
            {
                case "ToolStrip":
                    foreach (ToolStripItem item in ((ToolStrip)objControl).Items)
                    {
                        if (item is ToolStripTextBox)
                        {
                            Control_SetDefault(((ToolStripTextBox)item).TextBox, defaultHandle);
                        }
                        else if (item is ToolStripComboBox)
                        {
                            Control_SetDefault(((ToolStripComboBox)item).ComboBox, defaultHandle);
                        }
                    }

                    break;
                default:
                    foreach (Control item in objControl.Controls)
                    {
                        if (item is TextBox)
                        {
                            Control_SetDefault((TextBox)item, defaultHandle);
                        }
                    }

                    break;
            }
        }
    }

    public static void Event_Key_Press(object sender, KeyPressEventArgs e)
    {
        if (e.KeyChar == 'r')
        {
            if (((Control)sender).Tag is FormControlExt)
            {
                e.Handled = true;
                //
                Control_ForceValidate((Control)sender);
                //
                FormControlExt mField = (FormControlExt)((FormControlExt)sender).Tag;
                if (mField.DefaultHandle != null)
                    mField.DefaultHandle.Invoke(sender, null);
                if (mField.DefaultButton != null)
                    mField.DefaultButton.PerformClick();
            }
        }
    }

    public static void Control_ForceValidate(Control sender)
    {
        Type type = sender.GetType();
        type.InvokeMember("PerformControlValidation", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.InvokeMethod, null, sender, new object[] { true });
    }

    public static void Control_NextFocus(Control objControl)
    {
        Control objForm = objControl.Parent;
        Control objNext = objForm.GetNextControl(objControl, true);
        while ((objNext != null))
        {
            switch (objNext.GetType().Name)
            {
                case "TextBox":
                case "ComboBox":
                case "MultiColumnComboBox":
                    objNext.Focus();
                    break; // TODO: might not be correct. Was : Exit While

                default:
                    objNext = objForm.GetNextControl(objNext, true);
                    break;
            }
        }
    }

    public static void Control_FirstFocus(Control objControl)
    {
        Control objNext = objControl.GetNextControl(null, true);
        bool bFound = false;
        while ((objNext != null))
        {

            switch (objNext.GetType().Name)
            {

                case "TextBox":
                case "ToolStripTextBox":
                    bFound = objNext.Enabled && !((TextBox)objNext).ReadOnly;
                    break;
                case "ComboBox":
                case "ToolStripComboBox":
                case "MultiColumnComboBox":
                    bFound = objNext.Enabled;
                    break;
                case "TabControl":
                    Control_FirstFocus(((TabControl)objNext).SelectedTab);
                    break;
                case "ToolStrip":
                    if (ToolStrip_FirstFocus((ToolStrip)objNext))
                    {
                        break; // TODO: might not be correct. Was : Exit While
                    }
                    break;
                case "DataGridView":
                    break;
                //Nothing
                default:
                    if (objNext.HasChildren)
                    {
                        Control_FirstFocus(objNext);
                        break; // TODO: might not be correct. Was : Exit While
                    }
                    break;
            }
            if (bFound && objNext.TabStop)
            {
                objNext.Focus();
                break; // TODO: might not be correct. Was : Exit While
            }
            objNext = objControl.GetNextControl(objNext, true);
        }
    }

    public static bool ToolStrip_FirstFocus(ToolStrip objToolStrip)
    {
        bool bFound = false;
        foreach (ToolStripItem objNext in objToolStrip.Items)
        {
            switch (objNext.GetType().Name)
            {
                case "TextBox":
                case "ToolStripTextBox":
                    bFound = objNext.Enabled && !((ToolStripTextBox)objNext).ReadOnly;
                    if (bFound)
                        ((ToolStripTextBox)objNext).Focus();
                    break;
                case "ComboBox":
                case "MultiColumnComboBox":
                case "ToolStripComboBox":
                    bFound = objNext.Enabled;
                    if (bFound)
                        ((ToolStripComboBox)objNext).Focus();
                    break;
            }
            if (bFound)
            {
                //objNext.Focus()
                break; // TODO: might not be correct. Was : Exit For
            }
        }
        return bFound;
    }

    public static void TextBox_SetHandle(DataInputType eDataType, params TextBox[] arrayTextBox)
    {
        foreach (TextBox tb in arrayTextBox)
        {
            TextBox_SetHandle(tb, eDataType);
        }
    }

    public static void TextBox_SetHandle(TextBox tb, DataInputType eDataType)
    {
        TextBox_SetHandle(tb, eDataType, true);
    }

    public void TextBox_SetHandle(TextBox tb, string DataType)
    {
        TextBox_SetHandle(tb, DataType, true);
    }

    public static void TextBox_SetHandle(TextBox tb, DataInputType eDataType, bool AutoClearError)
    {
        TextBox_SetHandle(tb, eDataType, null, null, AutoClearError);
    }

    public static void TextBox_SetHandle(TextBox tb, string DataType, bool AutoClearError)
    {
        TextBox_SetHandle(tb, DataType, null, null, AutoClearError);
    }

    public static void TextBox_SetHandle(TextBox tbMin, TextBox tbMax, DataInputType eDataType)
    {
        TextBox_SetHandle(tbMin, tbMax, eDataType, null, null, true);
    }

    public static void TextBox_SetHandle(TextBox tbMin, TextBox tbMax, DataInputType eDataType, bool AutoClearError)
    {
        TextBox_SetHandle(tbMin, tbMax, eDataType, null, null, AutoClearError);
    }

    public static void TextBox_SetHandle(TextBox tbMin, TextBox tbMax, string DataType, bool AutoClearError)
    {
        TextBox_SetHandle(tbMin, tbMax, DataType, null, null, AutoClearError);
    }

    public static void TextBox_SetHandle(TextBox tbMin, TextBox tbMax, DataInputType eDataType, object MinValue, object MaxValue, bool AutoClearError)
    {
        TextBox_SetHandle(tbMin, eDataType, MinValue, tbMax, AutoClearError);
        TextBox_SetHandle(tbMax, eDataType, tbMin, MaxValue, AutoClearError);
    }

    public static void TextBox_SetHandle(TextBox tbMin, TextBox tbMax, string DataType, object MinValue, object MaxValue, bool AutoClearError)
    {
        TextBox_SetHandle(tbMin, DataType, MinValue, tbMax, AutoClearError);
        TextBox_SetHandle(tbMax, DataType, tbMin, MaxValue, AutoClearError);
    }

    public static void TextBox_SetHandle(TextBox tb, DataInputType eDataType, object MinValue, object MaxValue, bool AutoClearError)
    {
        string dataType = TextBox_GetDataType(eDataType);
        TextBox_SetHandle(tb, dataType, MinValue, MaxValue, AutoClearError);
    }

    public static string TextBox_GetDataType(DataInputType eDataType)
    {
        string dataType = Globals.Enum_GetName(eDataType);
        dataType = dataType.ToUpper().Substring(0, dataType.Length - 4);
        return dataType;
    }

    public static void TextBox_SetPattern(TextBox tb, string inputPattern)
    {
        TextBox_SetPattern(tb, inputPattern, true);
    }

    public static void TextBox_SetPattern(TextBox tb, string inputPattern, bool AutoClearError)
    {
        FormControlExt objFormControl = default(FormControlExt);
        if (tb.Tag == null)
        {
            objFormControl = new FormControlExt();
        }
        else
        {
            objFormControl = (FormControlExt)tb.Tag;
        }
        if (objFormControl.HandleObject == null)
        {
            objFormControl.HandleObject = new TextBoxHandle(tb, DataInputType.RegExData.ToString(), null, null);
        }
        ((TextBoxHandle)objFormControl.HandleObject).InputPattern = inputPattern;
        ((TextBoxHandle)objFormControl.HandleObject).AutoClearError = AutoClearError;
        ((TextBoxHandle)objFormControl.HandleObject).DataType = TextBox_GetDataType(DataInputType.RegExData);
        tb.Tag = objFormControl;
    }

    //Handle Input cho TextBox
    public static void TextBox_SetHandle(TextBox tb, string DataType, object MinValue, object MaxValue, bool AutoClearError)
    {
        //Purpose: 
        //   Handle cho TextBox
        //Parameters: 
        //   tb         : đối tượng TextBox
        //   DataType   : loại dữ liệu
        //   MinValue   : giá trị nhỏ nhất
        //   MaxValue   : giá trị lớn nhất
        //Notes
        FormControlExt objFormControl = default(FormControlExt);
        if (tb.Tag == null)
        {
            objFormControl = new FormControlExt();
        }
        else
        {
            objFormControl = (FormControlExt)tb.Tag;
        }
        if (objFormControl.HandleObject == null)
        {
            TextBoxHandle mHandle = new TextBoxHandle(tb, DataType, MinValue, MaxValue);
            mHandle.AutoClearError = AutoClearError;
            objFormControl.HandleObject = mHandle;
        }
        else
        {
            if ((MinValue != null))
                ((TextBoxHandle)objFormControl.HandleObject).MinValue = MinValue;
            if ((MaxValue != null))
                ((TextBoxHandle)objFormControl.HandleObject).MaxValue = MaxValue;
            ((TextBoxHandle)objFormControl.HandleObject).DataType = DataType;
        }
        if (DataType == "TIME")
            objFormControl.DataFormat = CS_DISPLAY_TIME_FORMAT;
        tb.Tag = objFormControl;
    }

    public static void TextBox_SetLookup(TextBox tb, LookupInvoker lookupMethod)
    {
        LookupInvokerEx LookUpEx = (TextBoxHandle txtHandle, LookupMode eMode) =>
        {
            lookupMethod.Invoke(txtHandle, eMode);
            return null;
        };
        TextBox_SetLookup(tb, LookUpEx);
    }

    public static void TextBox_SetLookup(TextBox tb, LookupInvoker lookupMethod, bool lookupRequired)
    {
        LookupInvokerEx LookUpEx = (TextBoxHandle txtHandle, LookupMode eMode) =>
        {
            lookupMethod.Invoke(txtHandle, eMode);
            return null;
        };
        TextBox_SetLookup(tb, LookUpEx);
        TextBox_GetHandle(tb).LookupRequired = lookupRequired;
    }

    public static void TextBox_SetLookup(TextBox tb, LookupInvokerEx lookupMethod, params Control[] arrControl)
    {
        TextBox_SetLookup(tb, lookupMethod, null, arrControl);
    }

    public static void TextBox_SetLookup(TextBox tb, LookupInvokerEx lookupMethod, MethodInvoker lookupChange, params Control[] arrControl)
    {
        //Purpose: 
        //   Handle lookup cho TextBox
        //Parameters: 
        //   tb          : đối tượng TextBox
        //   lookupMethod: thủ tục lookup
        //Notes
        FormControlExt objFormControl = default(FormControlExt);
        TextBoxHandle mHandle = default(TextBoxHandle);
        if (tb.Tag == null)
        {
            objFormControl = new FormControlExt();
        }
        else
        {
            objFormControl = (FormControlExt)tb.Tag;
        }
        if (objFormControl.HandleObject == null)
        {
            mHandle = new TextBoxHandle(tb, "TEXT", null, null);
            objFormControl.HandleObject = mHandle;
            tb.Tag = objFormControl;
        }
        else
        {
            mHandle = (TextBoxHandle)objFormControl.HandleObject;
        }
        objFormControl.Lookup = true;
        tb.Tag = objFormControl;
        mHandle.SetLookup(lookupMethod, arrControl);
        mHandle.LookupChanged(lookupChange);
    }

    public static void TextBox_ShowLookup(TextBox tb)
    {
        TextBoxHandle mHandle = TextBox_GetHandle(tb);
        if ((mHandle != null))
        {
            mHandle.ShowLookup();
        }
        else
        {
            throw new Exception("Textbox lookup method not found or not inited");
        }
    }

    public static TextBoxHandle TextBox_GetHandle(TextBox tb)
    {
        TextBoxHandle mHandle = null;
        if (tb.Tag is FormControlExt)
        {
            mHandle = (TextBoxHandle)((FormControlExt)tb.Tag).HandleObject;
        }
        return mHandle;
    }

    public static string TextBox_GetFormat(TextBox tb)
    {
        FormControlExt objFormControl = (FormControlExt)tb.Tag;
        if ((tb.Tag != null))
        {
            return objFormControl.DataFormat;
        }
        else
        {
            return null;
        }
    }

    public static void TextBox_SetFormat(string sFormat, params TextBox[] arrTextBox)
    {
        foreach (TextBox tb in arrTextBox)
        {
            TextBox_SetFormat(tb, sFormat);
        }
    }

    public static void TextBox_SetFormat(TextBox tb, string sFormat)
    {
        FormControlExt objFormControl = (FormControlExt)tb.Tag;
        if (tb.Tag == null)
        {
            objFormControl = new FormControlExt();
        }
        objFormControl.DataFormat = sFormat;
        tb.Tag = objFormControl;
    }

    public static void TextBox_SetScale(byte dataScale, params TextBox[] arrTextBox)
    {
        foreach (TextBox tb in arrTextBox)
        {
            TextBox_SetScale(tb, dataScale);
        }
    }

    public static void TextBox_SetScale(TextBox tb, byte dataScale)
    {
        FormControlExt objFormControl = (FormControlExt)tb.Tag;
        if (tb.Tag == null)
        {
            objFormControl = new FormControlExt();
        }
        objFormControl.DataScale = dataScale;
        tb.Tag = objFormControl;
    }

    public static byte TextBox_GetScale(TextBox tb)
    {
        FormControlExt objFormControl = (FormControlExt)tb.Tag;
        if ((tb.Tag != null))
        {
            return objFormControl.DataScale;
        }
        else
        {
            return 0;
        }
    }

    public static void TextBox_SetValue(TextBox tb, object oValue)
    {
        TextBox_SetValue(tb, oValue, true);
    }

    public static void TextBox_SetValue(TextBox tb, object oValue, bool bOverwrite)
    {
        if (!bOverwrite && !string.IsNullOrEmpty(tb.Text))
            return;
        FormControlExt objFormControl = (FormControlExt)tb.Tag;
        TextBoxHandle mHandle = default(TextBoxHandle);
        string sText = Object_GetDisplayValue(oValue);
        if (tb.Tag == null)
        {
            tb.Text = sText;
        }
        else
        {
            mHandle = (TextBoxHandle)objFormControl.HandleObject;
            if (objFormControl.Lookup)
            {
                mHandle.LookupValue = oValue;
            }
            else
            {
                if (!Null.IsNull(oValue) && !string.IsNullOrEmpty(objFormControl.DataFormat))
                {
                    if (oValue is System.DateTime)
                    {
                        tb.Text = ((System.DateTime)oValue).ToString(objFormControl.DataFormat);
                        //IsNumeric(oValue) Then
                    }
                    else if (oValue != null && Type_IsNumeric(oValue.GetType()))
                    {
                        tb.Text = Object_GetValue<decimal>(oValue).ToString(objFormControl.DataFormat);
                    }
                    else
                    {
                        tb.Text = sText;
                    }
                }
                else
                {
                    tb.Text = sText;
                }
            }
        }
    }

    public static object TextBox_GetValue(TextBox tb)
    {
        FormControlExt objFormControl = (FormControlExt)tb.Tag;
        TextBoxHandle mHandle = default(TextBoxHandle);
        if (tb.Tag == null || objFormControl.HandleObject == null)
        {
            return tb.Text;
        }
        else
        {
            mHandle = (TextBoxHandle)objFormControl.HandleObject;
            if (objFormControl.Lookup)
            {
                return mHandle.LookupValue;
            }
            else
            {
                return Object_SetValueEx(tb.Text, mHandle.DataType, false);
            }
        }
    }

    public static void TextBox_SetCase(CharacterCasing cCasing, params TextBox[] arrControl)
    {
        foreach (TextBox mControl in arrControl)
        {
            mControl.CharacterCasing = cCasing;
        }
    }


    public static T Find_Control<T>(Control mParentControl, string sName)
    {
        if (mParentControl.Controls.ContainsKey(sName))
        {
            return (T)(object)mParentControl.Controls[sName];
        }
        else
        {
            Control[] arrControl = mParentControl.Controls.Find(sName, true);
            if (arrControl.Length == 0)
                return (T)(object)null;
            return (T)(object)arrControl[0];
        }
    }

    public static object[] CheckedListBox_GetValue(CheckedListBox ctl)
    {
        List<object> retVal = new List<object>();
        for (int i = 0; i <= ctl.Items.Count - 1; i++)
        {
            if (ctl.GetItemChecked(i))
            {
                retVal.Add(((DataRowView)ctl.Items[i])[(ctl as ListControl).ValueMember]);
            }
        }
        return retVal.ToArray();
    }

    public static void CheckedListBox_SetValue(CheckedListBox ctl, string arrValue)
    {
        if (!string.IsNullOrEmpty(arrValue))
        {
            CheckedListBox_SetValue(ctl, arrValue.Split(','));
        }
        else
        {
            ctl.ClearSelected();
        }
    }

    public static void CheckedListBox_SetValue(CheckedListBox ctl, object[] arrValue)
    {
        for (int i = 0; i <= ctl.Items.Count - 1; i++)
        {
            ctl.SetItemChecked(i, Array.IndexOf(arrValue, ((DataRowView)ctl.Items[i])[(ctl as ListControl).ValueMember].ToString()) >= 0);
        }
    }

    public static void Combo_SetValue(ComboBox objCombo, object sValue)
    {
        Combo_SetValue(objCombo, sValue, false, "");
    }

    public static void Combo_SetValue(ComboBox objCombo, object sValue, bool bIgnoreError)
    {
        Combo_SetValue(objCombo, sValue, bIgnoreError, "");
    }

    public static void Combo_SetValue(ComboBox objCombo, object sValue, bool bIgnoreError, string sCorrectDisplay)
    {
        //Purpose: 
        //   Thủ tục để set giá trị cho ComboBox
        //   Hỗ trợ AutoCorrect giá trị không có trong Combo
        //Parameters: 
        //   objCombo        : đối tượng ComboBox 
        //   sValue          : giá trị cần set có thể là biến hoặc Object
        //   bAutoCorrect    : Yes/No
        //   sDisplay        : tên trường Value        

        //Handle dbnull value
        if (sValue == null || object.ReferenceEquals(sValue, DBNull.Value) || Null.IsNull(sValue))
        {
            if (objCombo.Items.Count > 0)
            {
                //Combo_SetValue(objCombo, COMBO_ITEM_NULL_VALUE)
                objCombo.SelectedIndex = 0;
            }
            return;
        }

        if (objCombo.Items.Count == 0 && !bIgnoreError && string.IsNullOrEmpty(sCorrectDisplay))
        {
            throw new Exception("Can't set value with blank combo: " + objCombo.Name);
        }

        bool bFound = false;
        object mSource = objCombo.DataSource;
        if (objCombo.Items.Count > 0)
        {
            objCombo.SelectedIndex = -1;
            if (mSource is DataView | mSource is DataTable)
            {
                DataView mDataView = null;

                if (mSource is DataView)
                {
                    mDataView = (DataView)mSource;
                }
                else
                {
                    mDataView = ((DataTable)mSource).DefaultView;
                }


                int i = 0;
                //= 0
                for (i = 0; i <= mDataView.Count - 1; i++)
                {
                    object oItemValue = mDataView[i][objCombo.ValueMember];
                    if (!Globals.IsDBNull(oItemValue) && oItemValue.Equals(sValue))
                    {
                        bFound = true;
                        break; // TODO: might not be correct. Was : Exit For
                    }
                }
                //If String.IsNullOrEmpty(mDataView.Sort) Then
                //    mDataView.Sort = objCombo.ValueMember
                //End If
                //'i = mDataView.Find(Object_GetDisplayValue(sValue))
                //i = mDataView.Find(sValue)
                //bFound = (i > -1)
                if (bFound)
                {
                    objCombo.SelectedIndex = (int)i;
                }
                else
                {
                    objCombo.SelectedIndex = 0;
                }
                //If sCorrectDisplay = "" Then Return
            }
            else
            {
                Type objType = objCombo.Items[0].GetType();
                PropertyInfo objProperty = Globals.Object_GetProperty(objType, objCombo.ValueMember);

                foreach (object objItem in objCombo.Items)
                {
                    if (objItem.GetType().Name == sValue.GetType().Name)
                    {
                        if (Object_Compare(objItem, sValue))
                        {
                            objCombo.SelectedItem = objItem;
                            bFound = true;
                            break; // TODO: might not be correct. Was : Exit For
                        }
                    }
                    else if (objProperty == null)
                    {
                        break; // TODO: might not be correct. Was : Exit For
                    }
                    else if (objProperty.GetValue(objItem, null).ToString() == sValue.ToString())
                    {
                        objCombo.SelectedItem = objItem;
                        bFound = true;
                        break; // TODO: might not be correct. Was : Exit For
                    }
                }
            }
        }
        if (bFound == false)
        {
            if (!string.IsNullOrEmpty(sCorrectDisplay))
            {
                if (objCombo.DataSource is DataTable)
                {
                    DataRow mRow = ((DataTable)objCombo.DataSource).NewRow();
                    mRow[objCombo.DisplayMember] = sCorrectDisplay;
                    mRow[objCombo.ValueMember] = sValue;
                    ((DataTable)objCombo.DataSource).Rows.Add(mRow);
                    objCombo.SelectedValue = sValue;
                }
                else if (objCombo.DataSource is DataView)
                {
                    DataRowView mRow = ((DataView)objCombo.DataSource).AddNew();
                    mRow[objCombo.DisplayMember] = sCorrectDisplay;
                    mRow[objCombo.ValueMember] = sValue;
                    objCombo.SelectedValue = sValue;
                }
                else
                {
                    ListBoxItem obj = new ListBoxItem(sValue.ToString(), sCorrectDisplay);
                    objCombo.Items.Add(obj);
                    objCombo.SelectedItem = obj;
                }
            }
            else
            {
                if (!string.IsNullOrEmpty(sCorrectDisplay))
                {
                    objCombo.Text = sCorrectDisplay;
                }
                else
                {
                    if (!bIgnoreError)
                        throw new Exception(string.Format("Item with value '{0}' not found in ComboBox: " + objCombo.Name, sValue));
                }
            }
        }
        else
        {
            //Dim s = DirectCast(objCombo, ComboBox).SelectedItem.Text
        }
        //reupdate view only text
        TextBox objView = Find_Control<TextBox>(objCombo.Parent, objCombo.Name + "_View");
        if ((objView != null))
        {
            objView.Text = ((ComboBox)objCombo).Text;
            //.SelectedItem.Text
        }
        //'
    }

    public static object Combo_GetValue(ToolStripComboBox objCombo)
    {
        return Combo_GetValue(objCombo.ComboBox);
    }

    public static object Combo_GetValue(ComboBox objCombo)
    {
        //Purpose: 
        //   Hàm lấy giá trị select của combo
        //Parameters: 
        //   objCombo    : đối tượng combobox
        //Notes

        bool mReturn = true;

        if ((objCombo.SelectedValue != null))
        {
            //Detech null item
            if (objCombo.DisplayMember == objCombo.ValueMember && objCombo.SelectedIndex == 0 && (DB_GetString(objCombo.SelectedValue) == COMBO_ITEM_SELECT_ALL || DB_GetString(objCombo.SelectedValue) == COMBO_ITEM_BLANK))
            {
                return null;
            }
            else
            {
                return objCombo.SelectedValue;
            }
            //If (objCombo.SelectedValue.ToString.IndexOf(COMBO_ITEM_NULL_VALUE) = 0 Or (objCombo.DisplayMember = objCombo.ValueMember)) _
            //    AndAlso (objCombo.SelectedText = COMBO_ITEM_NULL_TEXT OrElse objCombo.SelectedText = COMBO_ITEM_SELECT_ALL) Then
            //    Return COMBO_ITEM_NULL_VALUE
            //Else
            //    Return objCombo.SelectedValue
            //End If
            //Return objCombo.SelectedValue
        }
        else if ((objCombo.SelectedItem != null))
        {
            object objItem = objCombo.Items[objCombo.SelectedIndex];
            if (!string.IsNullOrEmpty(objCombo.ValueMember))
            {
                Type objType = objItem.GetType();
                PropertyInfo objProperty = Object_GetProperty(objType, objCombo.ValueMember);
                if (objProperty == null)
                {
                    return objItem;
                }
                else
                {
                    return objProperty.GetValue(objItem, null);
                }
            }
            else
            {
                return objItem;
            }
        }
        else
        {
            return Null.NullString;
            //COMBO_ITEM_NULL_VALUE
        }
    }

    public static void Control_FillInfo(Standard_Info si, Control c)
    {
        Control_FillInfo_Child(si, c);
    }

    public static T Control_FillInfo<T>(Standard_Info si, params Control[] c)
    {
        if (typeof(T).IsSubclassOf(typeof(Standard_Info)))
        {
            T info = Activator.CreateInstance<T>();
            if ((c != null) && (c.Length > 0))
            {
                foreach (Control item in c)
                {
                    Control_FillInfo_Child((Standard_Info)(object)info, item);
                }
            }

            return info;
        }
        return default(T);
    }

    public static void Control_FillInfo_Child(Standard_Info si, Control c)
    {
        if (c == null)
            return;
        string name = c.Name.Substring(3);
        object value = Control_GetValue(c);
        if (value != null)
        {
            si.SetPropertyValue(name, value);
        }
        foreach (Control cc in c.Controls)
        {
            Control_FillInfo_Child(si, cc);
        }
    }

    public static void TabControl_SelectedIndexChanged(object sender, EventArgs e)
    {
        try
        {
            Control_FirstFocus(((TabControl)sender).SelectedTab);
        }
        catch (Exception ex)
        {
            Message_Error(ex);
        }
    }

    public static void Control_ClearValue(Control ctrl)
    {
        if (ctrl is TextBox || ctrl is RichTextBox || ctrl is MaskedTextBox)
        {
            ctrl.Text = string.Empty;
        }
        else if (ctrl is ComboBox)
        {
            ((ComboBox)ctrl).SelectedIndex = 0;
        }
        else if (ctrl is MultiColumnComboBox)
        {
            ((MultiColumnComboBox)ctrl).SelectedIndex = 0;
        }
        else if (ctrl is DataGridView)
        {
            DataGridView dgv = (DataGridView)ctrl;
            if (dgv.DataSource != null)
                dgv.DataSource = null;
            else if (dgv.RowCount > 0)
                dgv.Rows.Clear();
        }
        foreach (Control i in ctrl.Controls)
        {
            Control_ClearValue(i);
        }
    }

    #region ======MessageBox.Show() automatically marshall to the UI Thread===============

    public static TaskbarNotifier taskbarNotifier;
    static void CloseClick(object obj, EventArgs ea)
    {
        //MessageBox.Show("Closed was Clicked");
        taskbarNotifier.Hide();
    }

    static void TitleClick(object obj, EventArgs ea)
    {
        //MessageBox.Show("Title was Clicked");
    }

    static void ContentClick(object obj, EventArgs ea)
    {
        //MessageBox.Show("Content was Clicked");
    }
    public static void CreateTaskbarNotifier()
    {
        taskbarNotifier = new TaskbarNotifier();
        //taskbarNotifier.SetCloseBitmap(new Bitmap(@"D:\WORKS\TaskbarNotifier\TaskbarNotifier_demo\TaskbarNotifierDemo\close.bmp"), Color.FromArgb(255, 0, 255), new Point(127, 8));
        taskbarNotifier.SetBackgroundBitmap(Lib.CommonForm.Properties.Resources.skin, Color.FromArgb(255, 0, 255));
        taskbarNotifier.TitleRectangle = new Rectangle(55, 9, 70, 25);
        taskbarNotifier.ContentRectangle = new Rectangle(8, 41, 133, 68);
        taskbarNotifier.TitleClick += new EventHandler(TitleClick);
        taskbarNotifier.ContentClick += new EventHandler(ContentClick);
        taskbarNotifier.CloseClick += new EventHandler(CloseClick);

        taskbarNotifier.CloseClickable = true;
        taskbarNotifier.TitleClickable = false;
        taskbarNotifier.ContentClickable = true;
        taskbarNotifier.EnableSelectionRectangle = true;
        taskbarNotifier.KeepVisibleOnMousOver = true;	// Added Rev 002
        taskbarNotifier.ReShowOnMouseOver = false;			// Added Rev 002

        //taskbarNotifier = new TaskbarNotifier();
        //taskbarNotifier.SetBackgroundBitmap(IBMS.CommonForm.Properties.Resources.skin, Color.FromArgb(255, 0, 255));
        //taskbarNotifier.TitleRectangle = new Rectangle(40, 9, 70, 25);
        //taskbarNotifier.ContentRectangle = new Rectangle(8, 41, 133, 68);
        //taskbarNotifier.CloseClickable = false;
        //taskbarNotifier.TitleClickable = false;
        //taskbarNotifier.ContentClickable = false;
        //taskbarNotifier.EnableSelectionRectangle = false;
        //taskbarNotifier.KeepVisibleOnMousOver = true;
        //taskbarNotifier.ReShowOnMouseOver = false;
    }

    public static void Message_InTaskbar(String msg)
    {
        taskbarNotifier.Show(Globals.assemblyTitle, msg, 500, 5000, 500);
    }


    /// <summary>
    /// Quá trình lưu dữ liệu, có transaction, hiển thị biểu tượng quay, thể hiện đang lưu dữ liệu
    /// </summary>
    /// <param name="_MethodAddress"></param>
    /// <param name="messageDoing"></param>
    /// <param name="messageDone"></param>
    public static void App_ProgressSave(MethodInvoker _MethodAddress, string messageDoing, string messageDone)
    {
        //string sTrans = "";
        //bool hasTrans = DataConnect.Check_Trans(ref sTrans);
        //if (!hasTrans)
        //    DataConnect.Begin_Trans();
        try
        {
            App_ProgressShow(_MethodAddress, messageDoing, messageDone);
            //if (!hasTrans)
            //    DataConnect.Commit_Trans();
        }
        catch
        {
            //if (!hasTrans)
            //    DataConnect.Rollback_Trans();
            throw;
        }
    }

    public static void App_ProgressSave(MethodInvoker _MethodAddress, string messageDoing)
    {
        App_ProgressSave(_MethodAddress, messageDoing, "");
    }

    public static void App_ProgressSave(MethodInvoker _MethodAddress)
    {
        App_ProgressSave(_MethodAddress, CS_DATA_SAVING, CS_DATA_SAVED);
    }

    /// <summary>
    /// Hiển thị biểu tượng quay, đang tải dữ liệu, hoặc đang thực hiện
    /// </summary>
    /// <param name="_MethodAddress"></param>
    public static void App_ProgressShow(MethodInvoker _MethodAddress)
    {
        frmProgress.Instance().Thread = _MethodAddress;
        frmProgress.Instance().Show_Progress();
    }

    public static void App_ProgressShow(MethodInvoker _MethodAddress, string sInitText)
    {
        frmProgress.Instance().Thread = _MethodAddress;
        frmProgress.Instance().Show_Progress(sInitText);
    }

    public static void App_ProgressShow(MethodInvoker _MethodAddress, string sInitText, string sFinishText)
    {
        frmProgress.Instance().Thread = _MethodAddress;
        frmProgress.Instance().Show_Progress(sInitText, sFinishText);
    }

    public static void App_ProgressShow(SubInvoker _SubAddress, object objInput, string sInitText)
    {
        frmProgress.Instance().ThreadSub = _SubAddress;
        frmProgress.Instance().ThreadInputObject = objInput;
        frmProgress.Instance().Show_Progress(sInitText);
    }

    public static object App_ProgressShow(FunctionInvoker _FunctionAddress, object objInput, string sDesc)
    {
        frmProgress.Instance().ThreadFunction = _FunctionAddress;
        frmProgress.Instance().ThreadInputObject = objInput;
        return frmProgress.Instance().Show_Progress(sDesc);
    }

    public static void App_ProgressText(string descText)
    {
        frmProgress.Instance().SetDescriptionText(descText);
    }

    public static void App_ProgressPause()
    {
        frmProgress.Instance().SetVisible(false);
    }

    public static void App_ProgressResume()
    {
        frmProgress.Instance().SetVisible(false);
    }

    #region Các hàm thông báo Message

    public static void Message_Error(Exception ex, string sDesc)
    {
        //Thủ tục hiện Error message 
        //Có thể hỗ trợ ghi lại lỗi hoặc translate lỗi thành message thân thiện hơn
        //will comming soon ...
        string sMessage = ex.Message;
        //Hỗ trợ hiển thị message từ việc raise lỗi trong database
        if (sMessage.Contains("[MSG]"))
        {
            sMessage = sMessage.Substring(sMessage.IndexOf("[MSG]") + "[MSG]".Length);
            if (sMessage.Contains("[/MSG]"))
                sMessage = sMessage.Substring(0, sMessage.IndexOf("[/MSG]")).Trim();
            Message_Warning(sMessage);
            return;
        }
        if (!App_IsDebug())
        {
            sMessage = "Some errors occurred while processing the requested tasks. Please contact system administrator for more details.";
            //Insert to error log here
            try
            {
                //SystemController.Instance().Error_Insert(Client_Info(), Environment_Info(), CS_USER_NAME, Function_Info(), ex);
            }
            catch (Exception ex2)
            {
                //SystemController.Instance().Error_Insert("Error", ex.Message, CS_USER_NAME, Function_Info(), ex2);
            }
        }
        else
        {
            if (!string.IsNullOrEmpty(sDesc))
            {
                sMessage = "Description: " + sDesc + Globals.vbCr;
            }
            else
            {
                sMessage = "";
            }
            sMessage = ex.Message.Replace(Globals.vbCrLf, Globals.vbCr + "     ");
            sMessage += "Message: " + sMessage;
            sMessage += Globals.vbCr + "Trace: " + ex.StackTrace;
        }
        MessageBox.Show(sMessage, Globals.Application_GetTitle(), MessageBoxButtons.OK, MessageBoxIcon.Warning);
    }


    public static bool Message_Delete(string objType)
    {
        return Message_Delete(objType, "");
    }

    public static bool Message_Delete(string objType, string sObjName)
    {
        //Hàm confirm khi xóa dữ liệu
        return Message_Confirm(CS_DELETE_CONFIRM + " " + objType + (string.IsNullOrEmpty(sObjName) ? "" : " '" + sObjName + "'"));
    }

    public static bool Message_Confirm(string sMessage)
    {
        return Message_Confirm(sMessage, false);
    }

    public static bool Message_Confirm(string sMessage, bool bShowRetry)
    {
        if (!sMessage.Trim().EndsWith("?") && !sMessage.Trim().EndsWith("."))
            sMessage += "?";
        //Hàm hiện message confirm 
        if (bShowRetry)
        {
            return (MessageBox.Show(sMessage, Globals.Application_GetTitle(), MessageBoxButtons.RetryCancel, MessageBoxIcon.Question) == DialogResult.Retry);
        }
        else
        {
            return (MessageBox.Show(sMessage, Globals.Application_GetTitle(), MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes);
        }
    }

    public static DialogResult Message_YesNoCancel(string sMessage)
    {
        //Hàm hiện message YesNoCancel
        return MessageBox.Show(sMessage, Globals.Application_GetTitle(), MessageBoxButtons.YesNoCancel, MessageBoxIcon.Question);
    }

    public static void Message_Information(string sMessage)
    {
        //Thủ tục hiện message information
        MessageBox.Show(sMessage, Globals.Application_GetTitle(), MessageBoxButtons.OK, MessageBoxIcon.Information);
    }

    public static void Message_Warning(string sMessage)
    {
        //Thủ tục hiện message warning
        MessageBox.Show(sMessage, Globals.Application_GetTitle(), MessageBoxButtons.OK, MessageBoxIcon.Warning);
    }

    public static void Message_Error(Exception ex)
    {
        Message_Error(ex, "");
    }
    #endregion
    

    public static string MessageTranslated(String Message)
    {
        String msg = "";
        if (Message.Contains("Invalid URI: The format of the URI could not be determined."))
            msg = "Địa chỉ kết nối không hợp lệ.";

        else if (Message.Contains("There was no endpoint"))
            msg = assemblyTitle + " không thể kết nối đến máy chủ vì một trong những lý do sau:" +
                   "\n1) Địa chỉ kết nối không tồn tại" +
                   "\n2) Mạng kết nối gặp sự cố.";

        else if (Message.Contains("Unable to connect to the remote server"))
            msg = assemblyTitle + " không thể kết nối đến máy chủ vì một trong những lý do sau:" +
                   "\n1) Địa chỉ kết nối không tồn tại" +
                   "\n2) Mạng kết nối gặp sự cố.";

        else if (Message.Contains("Could not connect to"))
            msg = assemblyTitle + " không thể kết nối đến máy chủ vì một trong những lý do sau:" +
                   "\n1) Địa chỉ kết nối không tồn tại" +
                   "\n2) Mạng kết nối gặp sự cố.";

        else if (Message.Contains("A network-related or instance-specific error occurred while establishing a connection to SQL Server."))
            msg = "SQL Server chưa được khởi động nên khi kết nối không tìm thấy SQL Server hoặc tên Server chưa đúng.";

        else if (Message.Contains("An unsecured or incorrectly secured fault was received from the other party")
            || Message.Contains("The communication object, System.ServiceModel.Channels.ServiceChannel, cannot be used for communication because it is in the Faulted state."))
            msg = assemblyTitle + " không thể kết nối đến máy chủ vì một trong những lý do sau:" +
                "\n1) Thông tin tài khoản không chính xác." +
                "\n2) Thời gian trên máy tính của bạn chênh lệch vượt quá 5 phút so với thời gian trên hệ thống máy chủ." +
                "\n3) Mạng kết nối gặp sự cố.";


        else if (Message.Contains("The remote server returned an unexpected response: (417) Expectation failed."))
            msg = Message;

        else if (Message.Contains("The remote server returned an error: (503) Server Unavailable."))
            msg = Message;

        else if (Message.Contains("Cannot access a disposed object."))
            msg = "Không thể truy cập một đối tượng đã bị hủy";

        else if (Message.Contains("'Temp$' is not a valid name"))
            msg = "Không tìm thấy Sheet có tên \"Temp\".";

        else if (Message.Contains("was deadlocked on lock resources"))
            msg = "Có người khác đang sử dụng tính năng này. Vui lòng chờ trong ít phút.";

        else if (Message.Contains("timed out"))
            msg = "Thời gian chờ đợi phản hồi vượt quá quy định vì một trong những lý do sau:" +
                "\n1) Server bị quá tải." +
                "\n2) Mạng kết nối quá chậm." +
                "\n3) Mạng kết nối gặp sự cố.";
        else
            msg = Message;

        if (!msg.Contains(Message))
            msg = msg + "\n\n-->" + Message;


        return msg;
    }

    #endregion

    //
    public static bool isRemoteWCF = true;
    public static string strUserName = "";
    public static string strPassword = "";
    public static int BranchID = 0;
    public static string BranchCode = "";
    public static string BranchShortName = "";
    public static string BranchName = "";
    public static int DepartmentID = 0;
    public static string DepartmentCode = "";
    public static string DepartmentName = "";
    public static string FullNameOfUser = "";
    public static bool isAdmin = true;
    public static bool viewAllCompany = false;
    public static bool viewAllBranch = false;
    public static DateTime SysToday = DateTime.MinValue;

    //

    #region ========= AlternatingRows, AllowUserEditRows, AddColumn DataGridView =========

    public static DataTable dgv_GetColumnHeaderText(DataGridView dgv, DataTable data)
    {
        //Remove columns of DataTable that not in DataGridView
        int i = 0;
        while (i < data.Columns.Count)
        {
            bool found = false;
            foreach (DataGridViewColumn dgvc in dgv.Columns)
            {
                if (dgvc.Name.ToLower() == data.Columns[i].ColumnName.ToLower() && dgvc.Visible)
                {
                    data.Columns[i].ColumnName = dgvc.HeaderText;
                    found = true;
                    break;
                }
            }
            if (!found)
                data.Columns.RemoveAt(i);
            else
                i++;
        }
        return data;
    }

    public static void dgv_MouseDown(object sender, MouseEventArgs e)
    {
        //Điều khiển cho phép sử dụng chuột phải để chọn dòng trên DataGridView
        DataGridView dgv = (DataGridView)sender;
        DataGridView.HitTestInfo Hti;//đối tượng cho biết thông tin hit trên datagridview
        if (e.Button == MouseButtons.Right)
        {
            //bắt sự kiện chuột phải
            Hti = dgv.HitTest(e.X, e.Y);//tạo đối tượng HTi

            if (Hti.Type == DataGridViewHitTestType.Cell)
            {
                //Kiểm tra xem đối tượng HTi có đúng là kiểu Cell không. Trường hợp này dành cho select full row
                if (dgv.SelectionMode == DataGridViewSelectionMode.FullRowSelect)
                {
                    if (!((DataGridViewRow)(dgv.Rows[Hti.RowIndex])).Selected)
                    {
                        //kiểm tra xem row tại vị trí chuột có đúng là chưa chọn
                        dgv.ClearSelection();//xóa chọn tất cả trên datagrid
                        ((DataGridViewRow)dgv.Rows[Hti.RowIndex]).Selected = true;//xác lập chọn cho row tại vị trí nhấn chuột
                        dgv.CurrentCell = dgv.Rows[Hti.RowIndex].Cells[Hti.ColumnIndex];
                    }
                }
                //Kiểm tra xem đối tượng HTi có đúng là kiểu Cell không. Trường hợp này dành cho select cell
                else if (dgv.SelectionMode == DataGridViewSelectionMode.CellSelect || dgv.SelectionMode == DataGridViewSelectionMode.RowHeaderSelect)
                {
                    if (!((DataGridViewCell)(dgv.Rows[Hti.RowIndex].Cells[Hti.ColumnIndex])).Selected)
                    {
                        //kiểm tra xem row tại vị trí chuột có đúng là chưa chọn
                        dgv.ClearSelection();//xóa chọn tất cả trên datagrid
                        ((DataGridViewCell)dgv.Rows[Hti.RowIndex].Cells[Hti.ColumnIndex]).Selected = true;//xác lập chọn cho row tại vị trí nhấn chuột
                        dgv.CurrentCell = dgv.Rows[Hti.RowIndex].Cells[Hti.ColumnIndex];
                    }
                }
            }
        }
        //-Nếu muốn bắt sự kiện với các phím Ctr, Shift ...thì ta thêm dòng lệnh sau:

        //if ((Control.ModifierKeys & Keys.Shift) == Keys.None && (Control.ModifierKeys & Keys.Control) == Keys.None)

        //dataTest.ClearSelection();
    }

    public static void dgv_ResizableIsFalse(DataGridView dgv, int StartIndex, int ToIndex)
    {
        for (int i = StartIndex; i < ToIndex; i++)
        {
            dgv.Columns[i].Resizable = DataGridViewTriState.False;
        }
    }

    public static void dgv_ResizableIsFalse(DataGridView dgv)
    {
        for (int i = 0; i < dgv.ColumnCount; i++)
        {
            dgv.Columns[i].Resizable = DataGridViewTriState.False;
        }
    }

    public static void dgv_ColumnsMaxWidth(DataGridView dgv, int Width, params string[] columns)
    {
        foreach (string item in columns)
        {
            dgv.Columns[item].Width = Width;
        }
    }

    public static void dgv_ColumnsMaxWidth(DataGridView dgv, params string[] columns)
    {
        dgv_ColumnsMaxWidth(dgv, 350, columns);
    }

    public static void dgv_ColumnsSortMode(DataGridView dgv, DataGridViewColumnSortMode mode, params string[] columns)
    {
        if (columns != null)
        {
            foreach (string item in columns)
            {
                dgv.Columns[item].SortMode = mode;
            }
        }
        else
        {
            foreach (DataGridViewColumn item in dgv.Columns)
            {
                dgv.Columns[item.Name].SortMode = mode;
            }
        }
    }

    public static void dgv_ColumnsSortMode(DataGridView dgv, DataGridViewColumnSortMode mode)
    {
        dgv_ColumnsSortMode(dgv, mode, null);
    }



    public static void dgv_DataSourceChanged(object sender, EventArgs e)
    {
        //Auto resize coulumns witdh
        dgv_AutoSizeColumnsMode_EndLoad((DataGridView)sender);
    }

    public static void dgv_CellEndEdit(object sender, DataGridViewCellEventArgs e)
    {
        //Auto resize coulumns witdh
        dgv_AutoSizeColumnsMode_EndLoad((DataGridView)sender);
    }

    public static void dgv_CellPainting(object sender, DataGridViewCellPaintingEventArgs e)
    {
        DataGridView dgv = (DataGridView)sender;
        if (e.RowIndex >= 0 && e.ColumnIndex >= 0)
        {
            if (dgv.Columns[e.ColumnIndex] == dgv.Columns["btnDelete"])
            {
                e.Paint(e.CellBounds, DataGridViewPaintParts.All);
                //DataGridViewButtonCell bc = dgvUsers[e.ColumnIndex, e.RowIndex] as DataGridViewButtonCell;
                //bool x;
                //if (bc.Tag == null)
                //{
                //    x = false;
                //}
                //else
                //{
                //    x = (bool)bc.Tag;
                //}
                //if (x)
                {
                    //Icon ico = new Icon("repair.ico");
                    dgv.Columns[e.ColumnIndex].Width = 25;
                    e.Graphics.DrawImage(Lib.CommonForm.Properties.Resources.Delete_Icon16, e.CellBounds.Left + 3, e.CellBounds.Top + 3);

                }
                e.Handled = true;
            }
            else if ((dgv.Columns[e.ColumnIndex] == dgv.Columns["btnError"]))
            {

                e.Paint(e.CellBounds, DataGridViewPaintParts.All);
                dgv.Columns[e.ColumnIndex].Width = 25;
                e.Graphics.DrawImage(Lib.CommonForm.Properties.Resources.Error16, e.CellBounds.Left + 3, e.CellBounds.Top + 3);
                e.Handled = true;
            }
        }
        //Ve lai ColumnHeader
        //if (e.RowIndex == -1 & e.ColumnIndex > -1)
        //{
        //    StringFormat format = new StringFormat();
        //    format.Alignment = StringAlignment.Center;
        //    format.LineAlignment = StringAlignment.Center;

        //    e.PaintBackground(e.CellBounds, true);
        //    e.Paint(e.CellBounds, DataGridViewPaintParts.ContentBackground);
        //    e.Graphics.DrawString(dgv.Columns[e.ColumnIndex].HeaderText, Control_StyleFont(e.CellStyle.Font, FormGlobals.CS_GRID_HEADER), new SolidBrush(Control_StyleColor(e.CellStyle.ForeColor, FormGlobals.CS_GRID_HEADER)), e.CellBounds, format);
        //    e.Handled = true;
        //}
    }

    public static void dgv_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e)
    {
        if (e.RowIndex >= 0 && e.ColumnIndex >= 0)
        {
            DataGridView dgv = (DataGridView)sender;

            if (dgv.Columns[e.ColumnIndex] == dgv.Columns["btnDelete"])
            {
                e.Value = "";
                e.FormattingApplied = true;

                //if (dgv.Columns[e.ColumnIndex].Width < 40)
                //{
                //    e.Value = "";
                //    e.FormattingApplied = true;
                //}
                //else
                //{
                //    dgv.Columns[e.ColumnIndex].DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleRight;
                //    e.Value = "Xóa";
                //    e.FormattingApplied = true;
                //}
            }
            else if (dgv.Columns[e.ColumnIndex] == dgv.Columns["btnError"])
            {
                e.Value = "";
                e.FormattingApplied = true;

                //if (dgv.Columns[e.ColumnIndex].Width < 40)
                //{
                //    e.Value = "";
                //    e.FormattingApplied = true;
                //}
                //else
                //{
                //    dgv.Columns[e.ColumnIndex].DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleRight;
                //    e.Value = "Lỗi";
                //    e.FormattingApplied = true;
                //}
            }
        }
    }

    public static void dgv_RowsAdded(object sender, DataGridViewRowsAddedEventArgs e)
    {
        //Auto resize coulumns witdh
        dgv_AutoSizeColumnsMode_EndLoad((DataGridView)sender);
    }
    public static void dgv_AutoSizeColumnsMode_BeginLoad(DataGridView dgv)
    {
        //Form nào cần thì mới gọi. Nên gọi ngay sau khi kết thúc việc AddColumns
        dgv.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.AllCells;
        dgv.AutoResizeColumns();
        dgv.DataSourceChanged += new EventHandler(dgv_DataSourceChanged);
        dgv.RowsAdded += new DataGridViewRowsAddedEventHandler(dgv_RowsAdded);
        dgv.CellEndEdit += new DataGridViewCellEventHandler(dgv_CellEndEdit);
    }
    public static void dgv_AutoSizeColumnsMode_EndLoad(DataGridView dgv)
    {
        //Tự động gọi sau khi bind DataSource. Người dùng có thể tự gọi nếu DataGridView dùng phương pháp insertrows (datagridview1..Rows.Insert(i, 1);)
        dgv.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.None;
        dgv.AutoResizeColumns(DataGridViewAutoSizeColumnsMode.AllCells);
        int maxWidth = 300;
        int width = 0;
        for (int j = 0; j < dgv.Columns.Count; j++)
        {
            dgv.Columns[j].Width = 0;
            for (int i = 0; i < dgv.Rows.Count; i++)
            {
                width = Math.Max(dgv.Columns[j].Width, dgv.Rows[i].Cells[j].PreferredSize.Width);
                if (width < maxWidth)
                    dgv.Columns[j].Width = width;
                else
                    dgv.Columns[j].Width = maxWidth;
            }

            width = Math.Max(dgv.Columns[j].Width, dgv.Columns[j].HeaderCell.PreferredSize.Width);
            if (width < maxWidth)
                dgv.Columns[j].Width = width;
            else
                dgv.Columns[j].Width = maxWidth;
        }
        dgv.AllowUserToResizeColumns = true;
        dgv.AllowUserToOrderColumns = true;
    }

    public static void dgv_Properties(DataGridView dgv)
    {
        dgv.RowHeadersWidth = 24;
        dgv.RowTemplate.Height = 22;//default:22

        dgv.ColumnHeadersDefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleLeft;
        dgv.ColumnHeadersDefaultCellStyle.WrapMode = DataGridViewTriState.False;

        //When use DisableResizing then AllowUserToResizeColumns auto false 
        dgv.ColumnHeadersHeightSizeMode = DataGridViewColumnHeadersHeightSizeMode.DisableResizing;
        dgv.ColumnHeadersHeight = 24;

        dgv.BorderStyle = BorderStyle.None;

        DataGridViewCellStyle dataGridViewCellStyle1 = new DataGridViewCellStyle();
        dataGridViewCellStyle1.ForeColor = SystemColors.ControlText;
        dataGridViewCellStyle1.SelectionBackColor = Color.FromArgb(210, 234, 246);
        dataGridViewCellStyle1.SelectionForeColor = SystemColors.WindowText;

        dgv.DefaultCellStyle = dataGridViewCellStyle1;

        //dgv.AlternatingRowsDefaultCellStyle.BackColor = Color.FromArgb(240, 240, 240);



        dgv.MouseDown += new MouseEventHandler(dgv_MouseDown);
        dgv.CellPainting += new DataGridViewCellPaintingEventHandler(dgv_CellPainting);
        dgv.CellFormatting += new DataGridViewCellFormattingEventHandler(dgv_CellFormatting);
    }
    

    public static void dgv_SelectionMode_FullRowSelect(DataGridView dgv)
    {
        dgv_Properties(dgv);
        dgv.AllowUserToAddRows = false;
        dgv.AllowUserToDeleteRows = false;
        dgv.AllowUserToOrderColumns = true;
        dgv.AllowUserToResizeColumns = true;
        dgv.AllowUserToResizeRows = false;
        dgv.RowHeadersVisible = false;
        dgv.SelectionMode = DataGridViewSelectionMode.FullRowSelect;
        dgv.MultiSelect = true;

    }

    public static void dgv_SelectionMode_CellSelect(DataGridView dgv, bool AllowUserToEditRows)
    {
        dgv_Properties(dgv);
        dgv.AllowUserToAddRows = AllowUserToEditRows;
        dgv.AllowUserToDeleteRows = AllowUserToEditRows;
        dgv.AllowUserToOrderColumns = true;
        dgv.AllowUserToResizeColumns = true;
        dgv.AllowUserToResizeRows = false;
        dgv.RowHeadersVisible = AllowUserToEditRows;
        dgv.SelectionMode = DataGridViewSelectionMode.RowHeaderSelect;
        dgv.MultiSelect = true;
    }

    private static void dgv_AddColumn(DataGridView dgv, DataGridViewColumn dgvC, string Name, string HeaderText, string Format, int Width, bool Visible, bool ReadOnly)
    {
        dgvC.Name = Name;
        dgvC.DataPropertyName = Name;
        dgvC.HeaderText = HeaderText;
        dgvC.Width = Width;
        dgvC.Visible = Visible;
        dgvC.ReadOnly = ReadOnly;

        dgv.Columns.Add(dgvC);

        if (Format.Contains("#") || Format == "R") //Nếu cột dạng số hoặc chọn căn phải thì căn về bên phải
            dgv.Columns[Name].DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleRight;
        //if (Format.Contains("/yy")) //Nếu cột dạng ngày thì căn về bên giữa
        //    dgv.Columns[Name].DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleCenter;
        if (Format == "C")
            dgv.Columns[Name].DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleCenter;

        if (Format.Length > 1)
            dgv.Columns[Name].DefaultCellStyle.Format = Format;

        if (dgv.Columns[Name].Index == 0)
        {
            dgv.Columns[Name].Resizable = DataGridViewTriState.False;
            dgv.AutoGenerateColumns = false;
        }
    }

    public static DataGridViewLinkColumn dgv_AddColumn_Link(DataGridView dgv, string Name, string HeaderText, string Format, int Width, bool Visible, bool ReadOnly)
    {
        DataGridViewLinkColumn col = new DataGridViewLinkColumn();
        dgv_AddColumn(dgv, col, Name, HeaderText, Format, Width, Visible, ReadOnly);
        return col;
    }

    public static DataGridViewImageColumn dgv_AddColumn_Image(DataGridView dgv, string Name, string HeaderText, string Format, int Width, bool Visible, bool ReadOnly)
    {
        DataGridViewImageColumn col = new DataGridViewImageColumn();
        dgv_AddColumn(dgv, col, Name, HeaderText, Format, Width, Visible, ReadOnly);
        return col;
    }

    public static DataGridViewButtonColumn dgv_AddColumn_Button(DataGridView dgv, string Name, string HeaderText, string Format, int Width, bool Visible, bool ReadOnly)
    {
        DataGridViewButtonColumn col = new DataGridViewButtonColumn();
        col.UseColumnTextForButtonValue = true;
        dgv_AddColumn(dgv, col, Name, HeaderText, Format, Width, Visible, ReadOnly);
        return col;
    }

    public static DataGridViewComboBoxColumn dgv_AddColumn_ComboBox(DataGridView dgv, string Name, string HeaderText, string Format, int Width, bool Visible, bool ReadOnly)
    {
        DataGridViewComboBoxColumn col = new DataGridViewComboBoxColumn();
        dgv_AddColumn(dgv, col, Name, HeaderText, Format, Width, Visible, ReadOnly);
        return col;
    }

    public static DataGridViewCheckBoxColumn dgv_AddColumn_CheckBox(DataGridView dgv, string Name, string HeaderText, string Format, int Width, bool Visible, bool ReadOnly)
    {
        DataGridViewCheckBoxColumn col = new DataGridViewCheckBoxColumn();
        dgv_AddColumn(dgv, col, Name, HeaderText, Format, Width, Visible, ReadOnly);
        return col;
    }

    public static DataGridViewTextBoxColumn dgv_AddColumn_TextBox(DataGridView dgv, string Name, string HeaderText, string Format, int Width, bool Visible, bool ReadOnly)
    {
        DataGridViewTextBoxColumn col = new DataGridViewTextBoxColumn();
        dgv_AddColumn(dgv, col, Name, HeaderText, Format, Width, Visible, ReadOnly);
        return col;

    }


    public static void dgv_ReSelection(DataGridView dgv, string ColumnName, object CellValue)
    {
        //--Re selection-----------------------------------------
        dgv.ClearSelection();//xóa chọn tất cả trên datagrid
        int n = dgv.Rows.Count;
        for (int i = 0; i < n; i++)
        {
            //Không xác định được chính xác RowIndex từ đầu vì có thể sẽ có 2 người cùng sinh ra chứng từ, 
            //lúc đó RowIndex xác định ban đầu sẽ ko còn đúng nữa. Vì vậy phải quét lại danh sách để tìm đúng vị trí (RowIndex)
            if (Globals.ToString(dgv.Rows[i].Cells[ColumnName].Value).ToLower().Equals(Globals.ToString(CellValue).ToLower()))
            {
                //-----CellSelect
                if (dgv.SelectionMode == DataGridViewSelectionMode.CellSelect || dgv.SelectionMode == DataGridViewSelectionMode.RowHeaderSelect)
                {
                    dgv.Rows[i].Cells[ColumnName].Selected = true;
                    dgv.CurrentCell = dgv.Rows[i].Cells[ColumnName];
                }
                else if (dgv.SelectionMode == DataGridViewSelectionMode.FullRowSelect || dgv.SelectionMode == DataGridViewSelectionMode.RowHeaderSelect)
                {
                    //-----FullRowSelect
                    dgv.Rows[i].Selected = true;
                    
                }
                break;
            }
        }
        //-------------------------------------------------------
    }

    public static object dgv_GetCellValue(DataGridView dgv, string ColumnName)
    {
        if (dgv.SelectionMode == DataGridViewSelectionMode.CellSelect || dgv.SelectionMode == DataGridViewSelectionMode.RowHeaderSelect)
        {
            return dgv.CurrentRow.Cells[ColumnName].Value;
        }
        else if (dgv.SelectionMode == DataGridViewSelectionMode.FullRowSelect || dgv.SelectionMode == DataGridViewSelectionMode.RowHeaderSelect)
        {
            if (dgv.SelectedRows.Count > 0)
                return dgv.SelectedRows[0].Cells[ColumnName].Value;
            else
                return null;
        }
        else
            return null;
    }

    public static object dgv_GetCellValue(DataGridView dgv, int index)
    {
        if (dgv.SelectionMode == DataGridViewSelectionMode.CellSelect || dgv.SelectionMode == DataGridViewSelectionMode.RowHeaderSelect)
        {
            return dgv.CurrentRow.Cells[index].Value;
        }
        else if (dgv.SelectionMode == DataGridViewSelectionMode.FullRowSelect || dgv.SelectionMode == DataGridViewSelectionMode.RowHeaderSelect)
        {
            if (dgv.SelectedRows.Count > 0)
                return dgv.SelectedRows[0].Cells[index].Value;
            else
                return null;
        }
        else
            return null;
    }

    public static DataRow dgv_GetDataRow(DataGridView dgv, int index)
    {
        if (dgv.DataSource == null)
            return null;
        DataTable dt = (DataTable)dgv.DataSource;

        if (dt.DefaultView.Count > index)
        {
            return dt.DefaultView[index].Row;
        }
        return null;
    }

    public static DataRow dgv_GetDataRow(DataGridView dgv)
    {
        if (dgv.SelectionMode == DataGridViewSelectionMode.CellSelect || dgv.SelectionMode == DataGridViewSelectionMode.RowHeaderSelect)
        {
            return dgv_GetDataRow(dgv, dgv.CurrentRow.Index);
        }
        else if (dgv.SelectionMode == DataGridViewSelectionMode.FullRowSelect || dgv.SelectionMode == DataGridViewSelectionMode.RowHeaderSelect)
        {
            if (dgv.SelectedRows.Count > 0)
                return dgv_GetDataRow(dgv, dgv.SelectedRows[0].Index);
            else
                return null;
        }
        else
            return null;
    }

    #endregion =================================================================================
    /// Lấy form đang active
    /// </summary>
    /// <returns></returns>
    public static Form GetActiveForm()
    {
        // Returns null for an MDI app
        Form activeForm = Form.ActiveForm;
        if (activeForm == null)
        {
            FormCollection openForms = Application.OpenForms;
            for (int i = 0; i < openForms.Count && activeForm == null; ++i)
            {
                Form openForm = openForms[i];
                //if(openForm.ActiveMdiChild!=null)
                //    activeForm = openForm.ActiveMdiChild;
                if (openForm.IsMdiContainer)
                {
                    activeForm = openForm.ActiveMdiChild;
                }
            }
        }

        return activeForm;
    }


    #region ====== Find note on Treeview =======================================================

    private static TreeNode firstnode = null;

    private static int searchlevel = -1;

    public static bool TreeView_FindNodeInHierarchy(TreeView tv, TreeNodeCollection nodes, string strSearchValue)
    {
        bool m_bNodeFound = false;
        searchlevel++;
        if (searchlevel == 0)
        {
            firstnode = null;
        }
        for (int iCount = 0; iCount < nodes.Count; iCount++)
        {
            if (nodes[iCount].Text.ToUpper().Contains(strSearchValue.ToUpper()))
            {
                if (firstnode == null)
                    firstnode = nodes[iCount];
                tv.SelectedNode = nodes[iCount];
                tv.Select();
                nodes[iCount].Expand();
                m_bNodeFound = true;
            }
            else
            {
                if (!TreeView_FindNodeInHierarchy(tv, nodes[iCount].Nodes, strSearchValue))
                    nodes[iCount].Collapse();
                else
                    m_bNodeFound = true;
            }
        }
        searchlevel--;
        if (searchlevel == 0 && firstnode != null)
        {
            tv.SelectedNode = firstnode;
            tv.Select();
        }
        return m_bNodeFound;
    }

    #endregion =================================================================================


}

